rts-sim-testing-service/third_party/message/radar.go

212 lines
5.7 KiB
Go
Raw Normal View History

2024-01-22 15:08:46 +08:00
package message
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
2024-01-24 17:12:34 +08:00
"sync/atomic"
2024-01-22 15:08:46 +08:00
)
const (
radar_head1 byte = 0x0C
radar_head2 byte = 0xFC
)
2024-01-24 17:12:34 +08:00
var autoInc = atomic.Int32{}
2024-01-22 16:35:50 +08:00
// 雷达与VOBC接口-雷达通讯协议
2024-01-24 17:12:34 +08:00
type RadarInfo struct {
AutoInc byte //自增计数器每发送一次自增1.范围0-256
RealSpeed uint16 //实际速度
DriftCounterS1 uint16 //位移计数器S1
DriftCounterS2 uint16 //位移计数器S2
InnerCheck1 byte //内部使用,我们只有在协议效验时用到该两个字节
InnerCheck2 byte //内部使用,我们只有在协议效验时用到该两个字节
2024-01-22 15:08:46 +08:00
State *RadarState
Tail byte
}
2024-01-24 17:12:34 +08:00
2024-01-22 15:08:46 +08:00
type RadarState struct {
2024-01-23 10:19:41 +08:00
SourceState byte //原数据
Model string // 天线模式
SyntheticalState string //综合状态
DirState string //方向状态
Dir string //方向
2024-01-22 15:08:46 +08:00
}
2024-01-24 17:12:34 +08:00
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))
}
buf = binary.LittleEndian.AppendUint16(buf, r.RealSpeed)
buf = binary.LittleEndian.AppendUint16(buf, r.DriftCounterS1)
buf = binary.LittleEndian.AppendUint16(buf, r.DriftCounterS2)
buf = append(buf, 0)
buf = append(buf, 0)
//6,7位 11
//3,4,5位 011
// 1位 1
//0位 1
buf = append(buf, 0|(byte(1)<<7)|(byte(1)<<6)|(byte(1)<<5)|(byte(1)<<4)|(byte(1)<<1)|(byte(1)<<0))
var sum int = 0
for _, d := range buf {
sum += int(d)
}
buf = append(buf, byte(^sum+1))
return buf
}
func (r *RadarInfo) Decode(data []byte) error {
2024-01-22 15:08:46 +08:00
if len(data) < 13 {
return fmt.Errorf("雷达数据预读取失败需要读取13字节可读取:%v", len(data))
}
buf := bytes.NewBuffer(data)
_, _, err := readHeader(buf)
if err != nil {
return err
}
autoInc := readByteData(buf)
speed := readSpeedOrCounter(buf)
s1 := readSpeedOrCounter(buf)
s2 := readSpeedOrCounter(buf)
i1, i2 := readRadarInnerData(buf)
state := readRadarState(buf)
tail := readByteData(buf)
r.AutoInc = autoInc
r.RealSpeed = speed
r.DriftCounterS1 = s1
r.DriftCounterS2 = s2
r.InnerCheck1 = i1
r.InnerCheck2 = i2
r.State = state
r.Tail = tail
2024-01-24 17:12:34 +08:00
if !(r.Tail == r.createTail()) {
2024-01-22 15:08:46 +08:00
return fmt.Errorf("数据解析完成,但协议效验不通过")
}
2024-01-22 16:35:50 +08:00
state.parseState()
2024-01-22 15:08:46 +08:00
return nil
}
2024-01-22 16:35:50 +08:00
func (s *RadarState) parseState() {
2024-01-23 09:58:17 +08:00
//第7位 == SW_Mode0, 第6位 == SW_Mode1
2024-01-22 16:35:50 +08:00
// 11:两个天线和双通道都OK
// 10DRS05_Single-Mode 40度,50度的天线或通道故障
// 01DRS05_Single-Mode 50度,40度的天线或通道故障
// 00错误模式 双侧天线或通道都故障
// 模式的工作差别工作在11.模式时效果最好。单模式10或01时可信度下降。
2024-01-22 15:08:46 +08:00
arr := s.getBitsStateArr()
2024-01-22 16:35:50 +08:00
s.Model = bitStateStr(arr[6:])
2024-01-23 09:58:17 +08:00
// 第5位=计算状态位,第4位=信号质量标志位,第3位=Black5out标志位
2024-01-22 16:35:50 +08:00
// 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 = bitStateStr(arr[0:1])
2024-01-22 15:08:46 +08:00
}
2024-01-23 09:58:17 +08:00
func (s *RadarState) getBitsStateArr() [8]byte {
//bits := make([]byte, 8)
var bits2 [8]byte = [8]byte{}
2024-01-22 15:08:46 +08:00
for i := 0; i < 8; i++ {
2024-01-22 16:35:50 +08:00
bit := s.SourceState >> uint(i) & 1
2024-01-23 09:58:17 +08:00
bits2[i] = bit
2024-01-22 15:08:46 +08:00
}
2024-01-23 09:58:17 +08:00
return bits2
2024-01-22 15:08:46 +08:00
}
func bitStateStr(data []byte) string {
var build = strings.Builder{}
2024-01-23 09:58:17 +08:00
for i := len(data) - 1; i >= 0; i-- {
build.WriteString(fmt.Sprintf("%v", data[i]))
2024-01-22 15:08:46 +08:00
}
2024-01-23 09:58:17 +08:00
/*for _, d := range data {
build.WriteString(fmt.Sprintf("%v", d))
}*/
2024-01-22 15:08:46 +08:00
return build.String()
}
2024-01-24 17:12:34 +08:00
func culDataSize(d uint16) int {
return int(d>>8) + int(d&0x00FF)
}
func (r *RadarInfo) createTail() byte {
var sum = int(radar_head1) + int(radar_head2)
sum += int(r.AutoInc)
sum += culDataSize(r.RealSpeed)
sum += culDataSize(r.DriftCounterS1)
sum += culDataSize(r.DriftCounterS2)
sum += int(r.InnerCheck1)
sum += int(r.InnerCheck2)
sum += int(r.State.SourceState)
return byte(^sum + 1)
2024-01-22 15:08:46 +08:00
}
2024-01-24 17:12:34 +08:00
2024-01-22 15:08:46 +08:00
func readHeader(buf *bytes.Buffer) (byte, byte, error) {
/*if buf.Len() < 2 {
return 0, 0, fmt.Errorf("雷达协议解析头部没有可读充足的数据")
}*/
d1, _ := buf.ReadByte()
d2, _ := buf.ReadByte()
2024-01-22 16:35:50 +08:00
if d1 == radar_head1 && d2 == radar_head2 {
return d1, d2, nil
2024-01-22 15:08:46 +08:00
}
2024-01-22 16:35:50 +08:00
return 0, 0, fmt.Errorf("雷达协议解析头部未找到对应的头部帧")
2024-01-22 15:08:46 +08:00
}
func readByteData(buf *bytes.Buffer) byte {
/* if buf.Len() < 1 {
return 0, fmt.Errorf("")
}*/
d, _ := buf.ReadByte()
return d
}
2024-01-24 17:12:34 +08:00
func readSpeedOrCounter(buf *bytes.Buffer) uint16 {
2024-01-22 15:08:46 +08:00
ss, _ := buf.ReadByte()
limit, _ := buf.ReadByte()
2024-01-24 17:12:34 +08:00
data := binary.LittleEndian.Uint16([]byte{ss, limit})
return data
//return &RadarData{SourceData: ss, valRange: limit, data: data}
2024-01-22 15:08:46 +08:00
}
func readRadarInnerData(buf *bytes.Buffer) (byte, byte) {
/*if buf.Len() < 2 {
return 0, 0, fmt.Errorf("")
}*/
i1, _ := buf.ReadByte()
i2, _ := buf.ReadByte()
return i1, i2
}
func readRadarState(buf *bytes.Buffer) *RadarState {
/*if buf.Len() < 1 {
return nil, fmt.Errorf("")
}*/
state, _ := buf.ReadByte()
2024-01-22 16:35:50 +08:00
return &RadarState{SourceState: state}
2024-01-22 15:08:46 +08:00
}
func driftCounter(buf *bytes.Buffer) (uint16, error) {
if buf.Len() < 2 {
return 0, fmt.Errorf("")
}
var driftCounter uint16
binary.Read(buf, binary.LittleEndian, &driftCounter)
return driftCounter, nil
}