列车pc仿真调整

This commit is contained in:
tiger_zhou 2024-04-19 16:55:51 +08:00
parent a13a01f99f
commit 20f9ac94c9
15 changed files with 352 additions and 164 deletions

View File

@ -250,6 +250,10 @@ type TrainEndsState struct {
AccOutSpeed int32 `protobuf:"varint,9,opt,name=accOutSpeed,proto3" json:"accOutSpeed,omitempty"`
// 雷达速度输出(米/秒)
RadarOutSpeed int32 `protobuf:"varint,10,opt,name=radarOutSpeed,proto3" json:"radarOutSpeed,omitempty"`
// 记录雷达设置检测时间的时间点,用于计算周期内的数字
RadarCheckTimeOverAt int64 `protobuf:"varint,11,opt,name=radarCheckTimeOverAt,proto3" json:"radarCheckTimeOverAt,omitempty"`
// 记录加速度计设置检测时间的时间点,用于计算周期内的数字
AccCheckTimeOverAt int64 `protobuf:"varint,12,opt,name=accCheckTimeOverAt,proto3" json:"accCheckTimeOverAt,omitempty"`
}
func (x *TrainEndsState) Reset() {
@ -354,6 +358,20 @@ func (x *TrainEndsState) GetRadarOutSpeed() int32 {
return 0
}
func (x *TrainEndsState) GetRadarCheckTimeOverAt() int64 {
if x != nil {
return x.RadarCheckTimeOverAt
}
return 0
}
func (x *TrainEndsState) GetAccCheckTimeOverAt() int64 {
if x != nil {
return x.AccCheckTimeOverAt
}
return 0
}
var File_common_data_proto protoreflect.FileDescriptor
var file_common_data_proto_rawDesc = []byte{
@ -398,7 +416,7 @@ var file_common_data_proto_rawDesc = []byte{
0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x64,
0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x12, 0x1c,
0x0a, 0x09, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x61, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28,
0x05, 0x52, 0x09, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x61, 0x64, 0x22, 0xa4, 0x03, 0x0a,
0x05, 0x52, 0x09, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x61, 0x64, 0x22, 0x88, 0x04, 0x0a,
0x0e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e,
0x61, 0x62, 0x6c, 0x65, 0x41, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x70, 0x65,
@ -425,10 +443,16 @@ var file_common_data_proto_rawDesc = []byte{
0x52, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x24, 0x0a,
0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70,
0x65, 0x65, 0x64, 0x42, 0x2f, 0x5a, 0x2d, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63,
0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x14, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63,
0x6b, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28,
0x03, 0x52, 0x14, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d,
0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x43, 0x68,
0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x18, 0x0c, 0x20,
0x01, 0x28, 0x03, 0x52, 0x12, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d,
0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x42, 0x2f, 0x5a, 0x2d, 0x6a, 0x6f, 0x79, 0x6c, 0x69,
0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73,
0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -107,6 +107,7 @@ type ConfigTrainEnds struct {
AccCheckTime int32 `json:"accCheckTime"` // 加速计储蓄时间
AccOutSpeed int32 `json:"accOutSpeed"` // 速传速度输出
RadarOutSpeed int32 `json:"radarOutSpeed"` // 雷达速度输出
}
type ConfigTrainData struct {
//Mass int32 `json:"mass" form:"mass"` // 列车的质量100=1ton

View File

@ -1537,7 +1537,7 @@ func (x *TrainDynamicState) GetDisplacement() int32 {
return 0
}
// vobc发过来的列车信息
// vobc发过来的列车信息 包括 (驾驶台和车载)
type TrainVobcState struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache

@ -1 +1 @@
Subproject commit acbfbf8b92d3702a9c0e6434f26fd6db2f57292d
Subproject commit 56e1948393aa51e0bf16d754292a211f348df161

View File

@ -11,7 +11,7 @@ import (
func TestAccUdp(t *testing.T) {
fmt.Println("准备启动ACC服务...")
addr := fmt.Sprintf("%v:%v", "127.0.0.1", "8899")
addr := fmt.Sprintf("%v:%v", "127.0.0.1", "9998")
server := udp.NewServer(addr, handle)
server.Listen()
select {}
@ -23,6 +23,6 @@ func handle(d []byte) {
if err == nil {
jsonD, _ := json.Marshal(ri)
fmt.Println(string(jsonD))
fmt.Println("接受数据:", string(jsonD))
}
}

View File

@ -7,14 +7,13 @@ import (
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
"math"
"sync"
"time"
)
type AccVobc interface {
Start(accManager AccVobcManager)
Stop()
SendAcc(acc *message.Accelerometer)
}
type AccVobcManager interface {
@ -27,10 +26,10 @@ var (
singleObj *accVobcService
)
const (
/*const (
accInterval = 15
accSpeedUnit = 9.8
)
)*/
func Default() AccVobc {
defer initLock.Unlock()
@ -52,13 +51,17 @@ func (acc *accVobcService) Start(accManager AccVobcManager) {
if config.RemoteIp == "" || config.RemotePort <= 0 || !config.Open {
}
acc.vobcClient = udp.NewClient(fmt.Sprintf("%v:%v", config.RemoteIp, config.RemotePort))
ctx, cancleFunc := context.WithCancel(context.Background())
acc.controlContext = cancleFunc
//ctx, cancleFunc := context.WithCancel(context.Background())
//acc.controlContext = cancleFunc
acc.radarVobcManager = accManager
go acc.sendTask(ctx)
//go acc.sendTask(ctx)
}
func (acc *accVobcService) sendTask(ctx context.Context) {
func (avs *accVobcService) SendAcc(acc *message.Accelerometer) {
avs.vobcClient.Send(acc.Encode())
}
/*func (acc *accVobcService) sendTask(ctx context.Context) {
for {
select {
case <-ctx.Done():
@ -74,7 +77,7 @@ func (acc *accVobcService) sendTask(ctx context.Context) {
}
time.Sleep(time.Millisecond * accInterval)
}
}
}*/
func (acc *accVobcService) Stop() {
if acc.controlContext != nil {

View File

@ -209,6 +209,7 @@ func (d *dynamics) TrainOperationConfig(req *message.TrainOperationConfig) error
return nil
}
data, _ := json.Marshal(req)
//fmt.Println(string(data))
url := d.buildUrl("/api/config/")
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {

View File

@ -57,7 +57,10 @@ func (s *electricalMachineryImpl) SendElectricMachineryMessage(info *message.Ele
if s.electricalMachineryUdpClient == nil {
return
}
s.electricalMachineryUdpClient.Send(info.Encode())
err := s.electricalMachineryUdpClient.Send(info.Encode())
if err != nil {
fmt.Println(err)
}
}
func (s *electricalMachineryImpl) initElectricalMachinery() {

View File

@ -0,0 +1,18 @@
package electrical_machinery
import (
"fmt"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
"testing"
)
func TestServer(t *testing.T) {
udpServer := udp.NewServer(fmt.Sprintf("127.0.0.1:%d", 9999), handleCanetFrames)
udpServer.Listen()
select {}
}
func handleCanetFrames(d []byte) {
msg := &message.ElectricMachinery{}
msg.Decode(d)
}

View File

@ -1,9 +1,8 @@
package message
import (
"bytes"
"encoding/binary"
"fmt"
"math"
)
const (
@ -12,18 +11,33 @@ const (
)
type Accelerometer struct {
Acc uint32
Acc float32
Aux byte
}
const (
FullScaleG = 0x80000000 // 1g的Q31表示
DataMask = 0xC0 // 最高2位是数据位
ReadingMask = 0xFFFFC000 // 屏蔽标志位和编码位
)
func (acc *Accelerometer) Encode() []byte {
accData := uint32(math.Round(float64(acc.Acc) * float64(FullScaleG)))
d2 := byte(accData >> 16)
d1 := byte(accData >> 8)
D0 := byte(accData) & 0xFF
D0 |= byte((accData >> 18) & DataMask)
data := make([]byte, 0)
data = append(data, accHeader)
data = append(data, uaidDefault)
acc.Acc = acc.Acc | 0x0000FF
data = binary.LittleEndian.AppendUint32(data, acc.Acc)
data = append(data, D0)
data = append(data, d1)
data = append(data, d2)
data = append(data, acc.Aux)
cs := checkSum(data)
data = append(data, ^cs+1)
return data
}
func checkSum(data []byte) byte {
@ -34,16 +48,16 @@ func checkSum(data []byte) byte {
return sum
}
func (acc *Accelerometer) Decode(data []byte) error {
if len(data) < 7 {
func (acc *Accelerometer) Decode(Packet []byte) error {
if len(Packet) < 7 {
return fmt.Errorf("")
}
buf := bytes.NewBuffer(data)
_, _ = buf.ReadByte()
_, _ = buf.ReadByte()
var dataInt uint32 = 0
binary.Read(buf, binary.LittleEndian, &dataInt)
//newData := math.Float32frombits(dataInt & 0xffffc000)
acc.Acc = dataInt & 0xffffc000
data := uint32(Packet[4])<<16 | uint32(Packet[3])<<8 | uint32(Packet[2])
// 应用屏蔽以移除标志位和编码位
data &= ReadingMask
// 将Q31值转换为float32加速度值g
acceleration := float32(float32(data) * (1.0 / float32(FullScaleG)))
fmt.Println(acceleration)
return nil
}

View File

@ -2,6 +2,7 @@ package message
import (
"encoding/binary"
"fmt"
"math"
)
@ -17,16 +18,33 @@ type ElectricMachinery struct {
func (t *ElectricMachinery) Encode() []byte {
b := []byte{0x01, 0x10, 0x60, 0xff, 0x00, 0x02, 0x04}
//hx := fmt.Sprintf("%X", b)
rotarySpeed := t.Speed * 60 / (float32(math.Pi) * float32(t.WheelDiameter) / 1000)
var rotarySpeedData uint32
if t.IsBack {
b = binary.BigEndian.AppendUint32(b, uint32(0-rotarySpeed))
//b = binary.BigEndian.AppendUint32(b, uint32(0-rotarySpeed))
rotarySpeedData = uint32(0 - rotarySpeed)
} else {
b = binary.BigEndian.AppendUint32(b, uint32(rotarySpeed))
//b = binary.BigEndian.AppendUint32(b, uint32(rotarySpeed))
rotarySpeedData = uint32(rotarySpeed)
}
b = binary.BigEndian.AppendUint32(b, rotarySpeedData)
crc := chkcrc(b) // crc校验码
b = binary.BigEndian.AppendUint16(b, crc)
//fmt.Println("发送:", hx, rotarySpeedData, crc)
return b
}
func (t *ElectricMachinery) Decode(d []byte) error {
if len(d) != 13 {
return fmt.Errorf("")
}
h := d[:7]
data := binary.BigEndian.Uint32(d[7:11])
crc := binary.BigEndian.Uint16(d[11:13])
hx := fmt.Sprintf("%X", h)
fmt.Println("接收", hx, data, crc)
return nil
}
// 生成crc
func chkcrc(data []byte) uint16 {

View File

@ -4,8 +4,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"strings"
"sync/atomic"
"math"
)
const (
@ -13,7 +12,11 @@ const (
radar_head2 byte = 0xFC
)
var autoInc = atomic.Int32{}
var autoInc byte = 0
var (
fixed_speed = 0.009155
driftDefaultVal = 0.1
)
// 雷达与VOBC接口-雷达通讯协议
type RadarInfo struct {
@ -27,49 +30,62 @@ type RadarInfo struct {
Tail byte
}
func NewRadarSender(speed float32, forward bool, displacement uint16) *RadarInfo {
state := &RadarState{SwModel1: 1, SwModel0: 1, calculateBit: 1, signalQualityBit: 1, BlackoutBit: 0, DirectionState: 1, Direction: IsTrue(forward)}
ri := &RadarInfo{State: state}
ri.RealSpeed = uint16(math.Abs(float64(speed*3.6) / fixed_speed))
if float64(displacement/10) > 9999 {
ri.DriftCounterS1 = 9999
} else {
ri.DriftCounterS1 = displacement / 10
}
if (float64(displacement) / 1000000) > 9999 {
ri.DriftCounterS2 = 9999
} else {
ri.DriftCounterS2 = uint16(float64(displacement) / 1000000)
}
return ri
}
type RadarState struct {
SourceState byte //原数据
Model string // 天线模式
SyntheticalState string //综合状态
DirState string //方向状态
Dir byte //方向
SwModel1 byte
SwModel0 byte
calculateBit byte //计算状态位
signalQualityBit byte //信号质量标志位
BlackoutBit byte //Blackout标志位
innerBit byte //内部使用
DirectionState byte //方向状态 1行驶方向有效 0行驶方向无效
Direction byte //行驶方向 1前向 0反向
}
func (r *RadarState) Encode() byte {
var state byte
state = setBit(state, 7, r.SwModel1)
state = setBit(state, 6, r.SwModel0)
state = setBit(state, 5, r.calculateBit)
state = setBit(state, 4, r.signalQualityBit)
state = setBit(state, 3, r.BlackoutBit)
state = setBit(state, 1, r.DirectionState)
state = setBit(state, 0, r.Direction)
return state
}
func (r RadarInfo) Encode() []byte {
buf := make([]byte, 0)
buf = append(buf, radar_head1)
buf = append(buf, radar_head2)
if tmp := autoInc.Add(1); tmp >= 256 {
autoInc.Store(0)
buf = append(buf, 0)
} else {
buf = append(buf, byte(tmp))
}
autoInc = autoInc + 1
buf = append(buf, autoInc)
buf = binary.LittleEndian.AppendUint16(buf, r.RealSpeed)
buf = binary.LittleEndian.AppendUint16(buf, r.DriftCounterS1)
buf = binary.LittleEndian.AppendUint16(buf, r.DriftCounterS2)
//buf = append(buf, byte(r.RealSpeed>>8))
//buf = append(buf, byte(r.RealSpeed&0x00FF))
//buf = append(buf, byte(r.DriftCounterS1>>8))
//buf = append(buf, byte(r.DriftCounterS1&0x00FF))
//buf = append(buf, byte(r.DriftCounterS2>>8))
//buf = append(buf, byte(r.DriftCounterS2&0x00FF))
buf = append(buf, 0)
buf = append(buf, 0)
//6,7位 11
//3,4,5位 011
// 1位 1
//0位 1
var state byte
state = setBit(state, 7, 1)
state = setBit(state, 6, 1)
state = setBit(state, 5, 1)
state = setBit(state, 4, 1)
state = setBit(state, 3, 0)
state = setBit(state, 1, 0)
state = setBit(state, 0, byte(r.State.Dir))
buf = append(buf, state)
buf = append(buf, r.State.Encode())
var sum = 0
for _, d := range buf {
sum += int(d)
@ -105,58 +121,19 @@ func (r *RadarInfo) Decode(data []byte) error {
if !(r.Tail == r.createTail()) {
return fmt.Errorf("数据解析完成,但协议效验不通过")
}
state.parseState()
return nil
}
func (s *RadarState) parseState() {
//第7位 == SW_Mode0, 第6位 == SW_Mode1
// 11:两个天线和双通道都OK
// 10DRS05_Single-Mode 40度,50度的天线或通道故障
// 01DRS05_Single-Mode 50度,40度的天线或通道故障
// 00错误模式 双侧天线或通道都故障
// 模式的工作差别工作在11.模式时效果最好。单模式10或01时可信度下降。
arr := s.getBitsStateArr()
s.Model = bitStateStr(arr[6:])
// 第5位=计算状态位,第4位=信号质量标志位,第3位=Black5out标志位
// 110计算状态高质量
// 地面信号反射良好,高精度的信号计算
// 100 计算状态,低质量
// 地面信号反射一般,信号计算可能会有缺陷
// 001 处于Blackout 状态
// 车辆行驶时无地面反射信号,无法进行信号计算
// 000 信号搜寻状态
// 在整个频率范围内搜寻多普勒信号,此时的速度和位移信息无效,当频率搜寻正确后,会转为计算模式。
s.SyntheticalState = bitStateStr(arr[3:6])
// 第1位 =方向状态
// 1行驶方向有效
// 0行驶方向无效
s.DirState = bitStateStr(arr[1:2])
// 第0位 =行驶方向
// 1前向
// 0反向
s.Dir = arr[0:1][0]
func (s *RadarState) Decode(d byte) {
s.SwModel1 = GetBit(d, 7)
s.SwModel0 = GetBit(d, 6)
s.calculateBit = GetBit(d, 5)
s.signalQualityBit = GetBit(d, 4)
s.BlackoutBit = GetBit(d, 3)
s.DirectionState = GetBit(d, 1)
s.Direction = GetBit(d, 0)
}
func (s *RadarState) getBitsStateArr() [8]byte {
//bits := make([]byte, 8)
var bits2 [8]byte = [8]byte{}
for i := 0; i < 8; i++ {
bit := s.SourceState >> uint(i) & 1
bits2[i] = bit
}
return bits2
}
func bitStateStr(data []byte) string {
var build = strings.Builder{}
for i := len(data) - 1; i >= 0; i-- {
build.WriteString(fmt.Sprintf("%v", data[i]))
}
/*for _, d := range data {
build.WriteString(fmt.Sprintf("%v", d))
}*/
return build.String()
}
func culDataSize(d uint16) int {
return int(d>>8) + int(d&0x00FF)
}
@ -169,7 +146,7 @@ func (r *RadarInfo) createTail() byte {
sum += culDataSize(r.DriftCounterS2)
sum += int(r.InnerCheck1)
sum += int(r.InnerCheck2)
sum += int(r.State.SourceState)
sum += int(r.State.Encode())
return byte(^sum + 1)
}
@ -213,7 +190,9 @@ func readRadarState(buf *bytes.Buffer) *RadarState {
return nil, fmt.Errorf("")
}*/
state, _ := buf.ReadByte()
return &RadarState{SourceState: state}
s := &RadarState{}
s.Decode(state)
return s
}
func driftCounter(buf *bytes.Buffer) (uint16, error) {

View File

@ -4,23 +4,21 @@ import (
"context"
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp"
"log/slog"
"math"
"sync"
"time"
)
type RadarVobc interface {
Start(radar RadarVobcManager)
Stop()
SendMsg(ri *message.RadarInfo)
}
type RadarVobcManager interface {
GetRunRadarConfig() config.RadarConfig
FindRadarTrain() *state_proto.TrainState
//FindRadarTrain() *state_proto.TrainState
}
const radar_interval = 15
@ -55,45 +53,47 @@ func (rv *radarVobc) Start(radar RadarVobcManager) {
}
rv.vobcClient = udp.NewClient(fmt.Sprintf("%v:%v", config.RemoteIp, config.RemotePort))
ctx, cancleFunc := context.WithCancel(context.Background())
rv.radarVobcTaskContext = cancleFunc
//ctx, cancleFunc := context.WithCancel(context.Background())
//rv.radarVobcTaskContext = cancleFunc
rv.radarVobcManager = radar
go rv.sendRadarInfo(ctx)
//go rv.sendRadarInfo(ctx)
}
// sendRadarInfo 发送速度,位移计数 给vobc
func (rv *radarVobc) SendMsg(ri *message.RadarInfo) {
rv.vobcClient.Send(ri.Encode())
} // sendRadarInfo 发送速度,位移计数 给vobc
/*
func (rv *radarVobc) sendRadarInfo(ctx context.Context) {
/*defer func() {
slog.Error("")
}()*/
for {
select {
case <-ctx.Done():
return
default:
}
trainStatus := rv.radarVobcManager.FindRadarTrain()
if trainStatus != nil {
hourSpeed := float64(trainStatus.DynamicState.Speed / 100)
trainDift := trainStatus.DynamicState.Displacement
td := float64(trainDift / 1000)
s1 := uint16(math.Round(td / driftDefaultVal))
s2 := uint16(math.Round(td / 1000 / driftDefaultVal))
ri := message.RadarInfo{RealSpeed: uint16(math.Round(hourSpeed / fixed_speed)), DriftCounterS1: s1, DriftCounterS2: s2}
ri.State = &message.RadarState{Dir: message.IsTrue(trainStatus.RunDirection)}
rv.vobcClient.SendMsg(ri)
for {
select {
case <-ctx.Done():
return
default:
}
trainStatus := rv.radarVobcManager.FindRadarTrain()
if trainStatus != nil {
hourSpeed := float64(trainStatus.DynamicState.Speed / 100)
trainDift := trainStatus.DynamicState.Displacement
td := float64(trainDift / 1000)
s1 := uint16(math.Round(td / driftDefaultVal))
s2 := uint16(math.Round(td / 1000 / driftDefaultVal))
ri := message.RadarInfo{RealSpeed: uint16(math.Round(hourSpeed / fixed_speed)), DriftCounterS1: s1, DriftCounterS2: s2}
ri.State = &message.RadarState{Dir: message.IsTrue(trainStatus.RunDirection)}
rv.vobcClient.SendMsg(ri)
}
time.Sleep(time.Millisecond * radar_interval)
}
time.Sleep(time.Millisecond * radar_interval)
}
}
*/
func (rv *radarVobc) Stop() {
if rv.radarVobcTaskContext != nil {
/* if rv.radarVobcTaskContext != nil {
rv.radarVobcTaskContext()
rv.radarVobcTaskContext = nil
}
}*/
if rv.vobcClient != nil {
rv.vobcClient.Close()
rv.vobcClient = nil

View File

@ -223,6 +223,23 @@ func UpdateConfigTrain(vs *VerifySimulation, ct *dto.ConfigTrainReqDto) {
trainState.TrainLength = ct.Length
trainState.WheelDiameter = ct.WheelDiameter
requestDynamicConfig(ct)
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.TrainEndsA.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) {
@ -328,6 +345,7 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
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)
@ -335,6 +353,7 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
sta.DynamicState.HeadRadarSpeed = speedParse(info.HeadRadarSpeed)
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
sta.DynamicState.Acceleration = info.Acceleration
sta.DynamicState.Displacement = int32(info.Displacement)
pluseCount(sta)
return sta

View File

@ -4,12 +4,16 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"joylink.club/bj-rtsts-server/dto/common_proto"
"joylink.club/bj-rtsts-server/third_party/acc"
"joylink.club/bj-rtsts-server/third_party/radar"
"log/slog"
"math"
"sort"
"strconv"
"strings"
"sync"
"time"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dto"
@ -287,12 +291,123 @@ func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainIn
}
// 更新列车状态
trainState := UpdateTrainStateByDynamics(s, trainId, info)
// 更新电机转速
electrical_machinery.Default().SendElectricMachineryMessage(&message.ElectricMachinery{
Speed: info.Speed,
WheelDiameter: trainState.WheelDiameter,
IsBack: trainState.VobcState.DirectionBackward,
})
sendElectricalMachinery(info, trainState)
sendRadar(info, trainState)
sendAcc(info, trainState)
}
// 发送电机控制命令
func sendElectricalMachinery(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
speed := info.Speed
sendMachinery := false
if trainState.VobcState.DirectionForward {
if trainState.TrainEndsA.SpeedSensorEnableA || trainState.TrainEndsA.SpeedSensorEnableB {
sendMachinery = true
speed = info.HeadSpeed2
if trainState.TrainEndsA.AccOutSpeed > 0 {
speed = float32(trainState.TrainEndsA.AccOutSpeed)
} else if trainState.TrainEndsA.SpeedSensorEnableA {
speed = info.HeadSpeed1
}
}
} else {
if trainState.TrainEndsB.SpeedSensorEnableA || trainState.TrainEndsB.SpeedSensorEnableB {
sendMachinery = true
speed = info.TailSpeed2
if trainState.TrainEndsB.AccOutSpeed > 0 {
speed = float32(trainState.TrainEndsB.AccOutSpeed)
} else if trainState.TrainEndsB.SpeedSensorEnableA {
speed = info.TailSpeed1
}
}
}
if sendMachinery {
// 更新电机转速
electrical_machinery.Default().SendElectricMachineryMessage(&message.ElectricMachinery{
Speed: speed,
WheelDiameter: trainState.WheelDiameter,
IsBack: trainState.VobcState.DirectionBackward,
})
}
}
// 发送雷达数据
func sendRadar(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
if trainState.VobcState.DirectionForward && trainState.TrainEndsA.RadarEnable {
s := parseRadarSpeedData(info.Speed, trainState.TrainEndsA)
radar.Default().SendMsg(message.NewRadarSender(s, true, info.Displacement))
} else if trainState.VobcState.DirectionBackward && trainState.TrainEndsB.RadarEnable {
s := parseRadarSpeedData(info.Speed, trainState.TrainEndsB)
radar.Default().SendMsg(message.NewRadarSender(s, false, info.Displacement))
} else {
slog.Error("列车行驶方向不确定或两端的雷达均未启用", "列车前进=", trainState.VobcState.DirectionForward, "雷达启用A=", trainState.TrainEndsA.RadarEnable, "列车后退=", trainState.VobcState.DirectionBackward, "雷达启用B=", trainState.TrainEndsB.RadarEnable)
}
}
func parseRadarSpeedData(radarSpeed float32, trainEndState *common_proto.TrainEndsState) float32 {
//如果差值速度和速度输出都填写,那么就以速度输出为优先
//如果动力学速度-差值速度小于0呢么输出的就是0不能小于0
timeOver := false
if time.Now().Unix() > trainEndState.RadarCheckTimeOverAt && trainEndState.RadarCheckTimeOverAt != 0 {
//判断雷达检测时间是否到期
timeOver = true
}
if trainEndState.RadarCheckSpeedDiff > 0 && trainEndState.RadarOutSpeed > 0 {
if timeOver {
//超时以动力学雷达速度为主
return radarSpeed
} else {
//如果雷达检测速度差值和速度输出都填写,那么就以速度输出为优先
return float32(trainEndState.RadarOutSpeed)
}
} else if trainEndState.RadarCheckSpeedDiff > 0 {
if timeOver {
return radarSpeed
} else {
//如果雷达检测速度差值填写,那么就以速度差值为主
return float32(math.Max(float64(radarSpeed)-float64(trainEndState.RadarCheckSpeedDiff), 0))
}
} else if trainEndState.RadarOutSpeed > 0 {
if timeOver {
return radarSpeed
} else {
//如果雷达速度输出填写,那么就以速度输出为主
return float32(trainEndState.RadarOutSpeed)
}
} else {
return radarSpeed
}
}
func sendAcc(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
if trainState.VobcState.DirectionForward && trainState.TrainEndsA.AccEnable {
s := parseAccSpeedData(info.Acceleration, trainState.TrainEndsA)
acc.Default().SendAcc(&message.Accelerometer{Acc: s})
} else if trainState.VobcState.DirectionBackward && trainState.TrainEndsB.AccEnable {
s := parseAccSpeedData(info.Acceleration, trainState.TrainEndsB)
acc.Default().SendAcc(&message.Accelerometer{Acc: s})
} else {
slog.Error("列车行驶方向不确定或两端的雷达均未启用", "列车前进=", trainState.VobcState.DirectionForward, "雷达启用A=", trainState.TrainEndsA.RadarEnable, "列车后退=", trainState.VobcState.DirectionBackward, "雷达启用B=", trainState.TrainEndsB.RadarEnable)
}
}
func parseAccSpeedData(accSpeed float32, trainEndState *common_proto.TrainEndsState) float32 {
//如果差值速度和速度输出都填写,那么就以速度输出为优先
//如果动力学速度-差值速度小于0呢么输出的就是0不能小于0
timeOver := false
if time.Now().Unix() > trainEndState.AccCheckTimeOverAt && trainEndState.AccCheckTimeOverAt != 0 {
//判断雷达检测时间是否到期
timeOver = true
}
if trainEndState.AccCheckSpeedDiff > 0 {
if timeOver {
return accSpeed
} else {
//如果雷达检测速度差值填写,那么就以速度差值为主
return float32(math.Max(float64(accSpeed)-float64(trainEndState.AccCheckSpeedDiff), 0))
}
} else {
return accSpeed
}
}
// 获取动力学配置信息
@ -581,7 +696,7 @@ func (s *VerifySimulation) GetRunAccConfig() config.AccConfig {
}
// FindRadarTrain 查找一个列车 只有1端雷达开启啊
func (s *VerifySimulation) FindRadarTrain() *state_proto.TrainState {
/*func (s *VerifySimulation) FindRadarTrain() *state_proto.TrainState {
var trainStatus *state_proto.TrainState
s.Memory.Status.TrainStateMap.Range(func(k any, v any) bool {
val, ok := v.(*state_proto.TrainState)
@ -590,18 +705,11 @@ func (s *VerifySimulation) FindRadarTrain() *state_proto.TrainState {
trainStatus = val
return false
}
/*if val.TrainEndsA.RadarEnable && val.TrainEndsB.RadarEnable {
return true
} else if val.TrainEndsA.RadarEnable || val.TrainEndsB.RadarEnable {
trainStatus = val
return false
}*/
}
return true
})
return trainStatus
}
}*/
// FindRadarTrain 查找一个列车 只有1端雷达开启啊
func (s *VerifySimulation) FindAccTrain() *state_proto.TrainState {