xlxs
This commit is contained in:
70
calculator/quaternion.go
Normal file
70
calculator/quaternion.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package calculator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Quaternion represents a quaternion with scalar (w) and vector (x, y, z) parts
|
||||
type Quaternion struct {
|
||||
w, x, y, z float64
|
||||
}
|
||||
|
||||
// Quaternion multiplication
|
||||
func (q1 Quaternion) Mul(q2 Quaternion) Quaternion {
|
||||
return Quaternion{
|
||||
w: q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z,
|
||||
x: q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y,
|
||||
y: q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x,
|
||||
z: q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w,
|
||||
}
|
||||
}
|
||||
|
||||
// Quaternion conjugate
|
||||
func (q Quaternion) Conjugate() Quaternion {
|
||||
return Quaternion{w: q.w, x: -q.x, y: -q.y, z: -q.z}
|
||||
}
|
||||
|
||||
// Rotate vector by quaternion
|
||||
func (q Quaternion) Rotate(v [3]float64) [3]float64 {
|
||||
qv := Quaternion{w: 0, x: v[0], y: v[1], z: v[2]}
|
||||
qConj := q.Conjugate()
|
||||
qvRotated := q.Mul(qv).Mul(qConj)
|
||||
return [3]float64{qvRotated.x, qvRotated.y, qvRotated.z}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 示例数据
|
||||
qBI := Quaternion{w: 1, x: 0, y: 0, z: 0} // 本体相对惯性系四元数
|
||||
posJ2000 := [3]float64{7000, 0, 0} // J2000位置
|
||||
// velJ2000 := [3]float64{0, 7.5, 0} // J2000速度
|
||||
|
||||
// 相机参数
|
||||
const numPixels = 9520
|
||||
const fov = 10.0 * math.Pi / 180 // 假设视场角为10度
|
||||
|
||||
// 逐像素计算地面交点
|
||||
for i := 0; i < numPixels; i++ {
|
||||
// 计算像素点相对光轴的偏角
|
||||
pixelOffset := (float64(i) - float64(numPixels)/2) / float64(numPixels)
|
||||
angle := pixelOffset * fov
|
||||
|
||||
// 假设光轴在本体坐标系中指向-z方向,计算视线方向
|
||||
dBody := [3]float64{-math.Sin(angle), 0, -math.Cos(angle)}
|
||||
|
||||
// 转换到惯性系
|
||||
dInertial := qBI.Rotate(dBody)
|
||||
|
||||
// 计算地面交点(假设dInertial已经标准化)
|
||||
k := -posJ2000[2] / dInertial[2] // 简化的交点计算
|
||||
groundPoint := [3]float64{
|
||||
posJ2000[0] + k*dInertial[0],
|
||||
posJ2000[1] + k*dInertial[1],
|
||||
posJ2000[2] + k*dInertial[2],
|
||||
}
|
||||
|
||||
// 转换到地理坐标
|
||||
lat, lon, _ := ECEFToGeodetic(groundPoint[0], groundPoint[1], groundPoint[2])
|
||||
fmt.Printf("Pixel %d: Latitude: %f, Longitude: %f\n", i, lat, lon)
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
var (
|
||||
dataId string
|
||||
batch bool
|
||||
output string
|
||||
)
|
||||
|
||||
var extractCmd = &cobra.Command{
|
||||
@@ -31,7 +32,7 @@ var extractCmd = &cobra.Command{
|
||||
} else {
|
||||
p := &extract.Params{
|
||||
InputData: fmt.Sprintf("demo/data/%s.dat", dataId),
|
||||
OutputPath: fmt.Sprintf("demo/output/%s", dataId),
|
||||
OutputPath: fmt.Sprintf("%s/%s", output, dataId),
|
||||
TempPath: fmt.Sprintf("demo/temp/%s", dataId),
|
||||
DataId: dataId,
|
||||
Satellite: "SJY01",
|
||||
@@ -51,16 +52,18 @@ func init() {
|
||||
|
||||
extractCmd.Flags().StringVarP(&dataId, "data-id", "d", "051622", "051622")
|
||||
extractCmd.Flags().BoolVarP(&batch, "batch", "b", false, "true | false")
|
||||
extractCmd.Flags().StringVarP(&output, "out", "o", "demo/output", "demo/output")
|
||||
}
|
||||
|
||||
func params() []*extract.Params {
|
||||
var params []*extract.Params
|
||||
datas := []string{"051513", "051622",
|
||||
"051712", "051721", "051821", "051823", "051921", "051922", "Q051723"}
|
||||
datas := []string{"051622", "051712", "051721",
|
||||
"051813", "051821", "051823",
|
||||
"051921", "051922", "052022"}
|
||||
for _, d := range datas {
|
||||
params = append(params, &extract.Params{
|
||||
InputData: fmt.Sprintf("demo/data/%s.dat", d),
|
||||
OutputPath: fmt.Sprintf("demo/output/%s", d),
|
||||
OutputPath: fmt.Sprintf("%s/%s", output, d),
|
||||
TempPath: fmt.Sprintf("demo/temp/%s", d),
|
||||
DataId: d,
|
||||
Satellite: "SJY01",
|
||||
|
||||
@@ -24,12 +24,14 @@ var parseCmd = &cobra.Command{
|
||||
e := extract.NewExtractor(¶ms)
|
||||
// p.ParseAuxPlatformWithHead("demo/ref/辅助数据.dat")
|
||||
fmt.Println("Reference Time: 2000-01-01 12:00:00 UTC, seconds:", extract.Time2000UTCSec())
|
||||
_, err := e.ParseAuxPlatform("demo/output/051622/SJY01_PMS_20240516_101236_051622_096.AUX")
|
||||
err := e.ExtractAux("demo/output/051622/SJY01_PMS_20240516_101236_051622_096.AUX",
|
||||
"demo/temp/1.xlsx")
|
||||
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
// p.ParseAuxEBox("demo/output/SJY01_PMS_20240516_101236_051622_096_EB.AUX")
|
||||
e.ParseAuxPlatform("demo/output/Q052100/SJY01_PMS_20240519_121433_Q052100_102.AUX")
|
||||
// e.ParseAuxPlatform("demo/output/Q052100/SJY01_PMS_20240519_121433_Q052100_102.AUX")
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package extract
|
||||
|
||||
/*
|
||||
将欧拉角 (yaw, pitch, roll) 转换为旋转矩阵
|
||||
|
||||
参数:
|
||||
- yaw: 偏航角(绕Z轴旋转)
|
||||
- pitch: 俯仰角(绕Y轴旋转)
|
||||
- roll: 滚转角(绕X轴旋转)
|
||||
*/
|
||||
379
extract/aux.go
379
extract/aux.go
@@ -1,380 +1,45 @@
|
||||
package extract
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tealeg/xlsx"
|
||||
)
|
||||
|
||||
// 每行传感器数据帧头信息长度为24字节
|
||||
type AuxFrameHead struct {
|
||||
PkgHead [4]byte // 包头头标识符,固定为0xD15BD15B
|
||||
FillByte0 byte // 填充字节 0x00
|
||||
FrmHead [6]byte // 帧头标识符,固定为0xEB90EB90EB90
|
||||
// 图像模式
|
||||
// B7 模式标识 000:为线阵模式
|
||||
// B6
|
||||
// B5
|
||||
// B4 B4谱状态 0:不输出1:输出
|
||||
// B3 B3谱状态 0:不输出1:输出
|
||||
// B2 B2谱状态 0:不输出1:输出
|
||||
// B1 B1谱状态 0:不输出1:输出
|
||||
// B0 全色状态 0:不输出1:输出
|
||||
ImgMode byte
|
||||
SerialNo uint32 // 当前流水号
|
||||
TimeSec uint32 // 时间(秒)
|
||||
TimeSecFrac uint32 // 秒小数 量纲:1us/bit,十六进制无符号整型数
|
||||
FileNo uint8 // 文件号
|
||||
|
||||
IsValidFrmHead bool
|
||||
B0 bool
|
||||
B1 bool
|
||||
B2 bool
|
||||
B3 bool
|
||||
B4 bool
|
||||
IsLinerMatrix bool
|
||||
RowLength int
|
||||
}
|
||||
|
||||
func (afh *AuxFrameHead) Decode(data []byte) error {
|
||||
if len(data) < 24 {
|
||||
return errors.New("length of AuxFrameHead is not 24")
|
||||
}
|
||||
|
||||
afh.PkgHead = [4]byte{data[0], data[1], data[2], data[3]}
|
||||
afh.FillByte0 = data[4]
|
||||
afh.FrmHead = [6]byte{data[5], data[6], data[7], data[8], data[9], data[10]}
|
||||
afh.ImgMode = data[11]
|
||||
afh.B0 = (afh.ImgMode&(1<<0) != 0x0)
|
||||
afh.B1 = (afh.ImgMode&(1<<1) != 0x0)
|
||||
afh.B2 = (afh.ImgMode&(1<<2) != 0x0)
|
||||
afh.B3 = (afh.ImgMode&(1<<3) != 0x0)
|
||||
afh.B4 = (afh.ImgMode&(1<<4) != 0x0)
|
||||
afh.IsLinerMatrix = (afh.ImgMode&(1<<5) == 0x0 && afh.ImgMode&(1<<6) == 0x0 && afh.ImgMode&(1<<7) == 0x0)
|
||||
afh.SerialNo = binary.BigEndian.Uint32(data[12:16])
|
||||
afh.TimeSec = binary.BigEndian.Uint32(data[16:20])
|
||||
afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22]))
|
||||
afh.FileNo = data[23]
|
||||
|
||||
afh.RowLength = afh.LengthOfRow()
|
||||
afh.IsValidFrmHead = afh.CheckFrmHead()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 计算一行数据长度:帧头+辅助数据+图像数据
|
||||
func (afh AuxFrameHead) LengthOfRow() int {
|
||||
if !afh.IsLinerMatrix {
|
||||
return 14344
|
||||
}
|
||||
|
||||
length := 64 // 帧头+辅助数据长度
|
||||
if afh.B0 {
|
||||
length += 19040
|
||||
}
|
||||
if afh.B1 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B2 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B3 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B4 {
|
||||
length += 1192
|
||||
}
|
||||
|
||||
return length
|
||||
}
|
||||
|
||||
func (afh AuxFrameHead) CheckFrmHead() bool {
|
||||
if afh.FrmHead[0] == 0xEB && afh.FrmHead[1] == 0x90 &&
|
||||
afh.FrmHead[2] == 0xEB && afh.FrmHead[3] == 0x90 &&
|
||||
afh.FrmHead[4] == 0xEB && afh.FrmHead[5] == 0x90 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
|
||||
func (e *Extractor) SeprateAuxAndImgData(dataFile string, segmentIndex int) error {
|
||||
// 打开传输帧文件 - 一次读入内存
|
||||
data, err := os.ReadFile(dataFile)
|
||||
if err != nil {
|
||||
log.Println("read data from", dataFile, "error:", err.Error())
|
||||
func (e Extractor) ExtractAux(auxfile, xlsxfile string) error {
|
||||
if err := createAuxXlxs(xlsxfile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("seprate aux and img data from", dataFile)
|
||||
|
||||
dataLen := len(data)
|
||||
log.Info("length of original data: ", dataLen)
|
||||
var firstFrmHead *AuxFrameHead
|
||||
data, firstFrmHead = e.trimImgRawData(data)
|
||||
dataLen = len(data)
|
||||
log.Info("after trim,length of data: ", dataLen)
|
||||
e.quanlityAnalysis(data)
|
||||
|
||||
outputDir := e.params.OutputPath
|
||||
name := strings.Join([]string{
|
||||
e.params.Satellite,
|
||||
"PMS",
|
||||
time.Unix(int64(firstFrmHead.TimeSec)+int64(ReferenceTime2000),
|
||||
int64(firstFrmHead.TimeSecFrac)*1000).
|
||||
Format("20060102_150405"),
|
||||
e.params.DataId,
|
||||
fmt.Sprintf("%03d", firstFrmHead.FileNo),
|
||||
}, "_")
|
||||
|
||||
lw := newL0Writer(outputDir, name)
|
||||
defer lw.Close()
|
||||
|
||||
var panEnviHdr, mssEnviHdr EnviHdr
|
||||
|
||||
var afh AuxFrameHead
|
||||
|
||||
msdata := make([][]byte, 4)
|
||||
var header []byte
|
||||
var ebAux []byte
|
||||
var platAux []byte
|
||||
|
||||
for i := 0; i < dataLen; {
|
||||
if i+4 > dataLen {
|
||||
logrus.Println("end of data, dataLen:", dataLen, "i:", i)
|
||||
break
|
||||
}
|
||||
|
||||
// 包头
|
||||
if data[i] == 0xD1 && data[i+1] == 0x5B && data[i+2] == 0xD1 && data[i+3] == 0x5B {
|
||||
log.Debug("find package head: 0xD15BD15B")
|
||||
} else {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析帧
|
||||
if i+24 > dataLen {
|
||||
log.Info("length of frame head is not engough for frame head")
|
||||
break
|
||||
}
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Info("invalid frame head of original raw data")
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
// 目前只支持线阵模式
|
||||
if !afh.IsLinerMatrix {
|
||||
log.Error("not liner matrix mode, only support liner matrix mode")
|
||||
break
|
||||
}
|
||||
|
||||
// 读取一行数据 data[i : i+afh.RowLength]
|
||||
if i+afh.RowLength > dataLen {
|
||||
log.Infof("length of image row data %v is not enough: %v", dataLen-i, afh.RowLength)
|
||||
break
|
||||
}
|
||||
|
||||
auxTime := binary.BigEndian.Uint32(data[i+32 : i+36])
|
||||
if math.Abs(float64(auxTime)-float64(afh.TimeSec)) < 30 {
|
||||
header = append(header, data[i:i+24]...)
|
||||
}
|
||||
// 存储辅助数据到临时文件
|
||||
dataIndex := i + 24
|
||||
// lw.ws[EB_AUX].w.Write(data[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据
|
||||
ebAux = append(ebAux, data[dataIndex:dataIndex+8]...)
|
||||
dataIndex += 8
|
||||
// lw.ws[PLAT_AUX].w.Write(data[dataIndex : dataIndex+32]) // 32字节中心机辅助数据
|
||||
platAux = append(platAux, data[dataIndex:dataIndex+32]...)
|
||||
dataIndex += 32
|
||||
|
||||
// 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件
|
||||
if afh.B0 {
|
||||
// wpan.Write(data[dataIndex : dataIndex+19040])
|
||||
write16bPixelLittleEndian(lw.ws[PAN_RAW].w, data[dataIndex:dataIndex+19040])
|
||||
dataIndex += 19040
|
||||
panEnviHdr.Lines += 1
|
||||
}
|
||||
|
||||
if afh.B1 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[0] = append(msdata[0], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
mssEnviHdr.Lines += 1
|
||||
}
|
||||
if afh.B2 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[1] = append(msdata[1], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
if afh.B3 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[2] = append(msdata[2], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
if afh.B4 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[3] = append(msdata[3], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
i = dataIndex // 完成一行数据解析
|
||||
}
|
||||
|
||||
// var bands = 0
|
||||
// for i := 0; i < 4; i++ {
|
||||
// if len(msdata[i]) > 0 {
|
||||
// log.Println("write mss data of band B", i+1)
|
||||
// _, err := write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[i])
|
||||
// if err != nil {
|
||||
// log.Error("write mss data error:", err.Error())
|
||||
// }
|
||||
// bands += 1
|
||||
// }
|
||||
// }
|
||||
|
||||
if len(msdata[0]) != len(msdata[1]) || len(msdata[2]) != len(msdata[3]) {
|
||||
log.Error("mss data of bands B1-B4 are not equal")
|
||||
return errors.New("mss data of bands B1-B4 are not equal")
|
||||
}
|
||||
|
||||
mssRowLen := 1192 * 4
|
||||
for i := 0; i < len(msdata[0]); i += mssRowLen {
|
||||
var err error
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[0][i:i+mssRowLen])
|
||||
wb, err := xlsx.OpenFile(xlsxfile)
|
||||
if err != nil {
|
||||
log.Error("write mss 1 data error:", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[1][i:i+mssRowLen])
|
||||
|
||||
sh := wb.Sheets[0]
|
||||
|
||||
data, err := os.ReadFile(auxfile)
|
||||
if err != nil {
|
||||
log.Error("write mss 2 data error:", err.Error())
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[2][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 3 data error:", err.Error())
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[3][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 4 data error:", err.Error())
|
||||
}
|
||||
log.Println("read aux data from", auxfile, "error:", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
panEnviHdr.Samples = 9520
|
||||
panEnviHdr.Bands = 1
|
||||
lw.ws[PAN_HDR].w.Write([]byte(panEnviHdr.String()))
|
||||
for i := 0; i < len(data); i += 24 + 128 + 512 {
|
||||
row := sh.AddRow()
|
||||
|
||||
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
|
||||
mssEnviHdr.Samples = 2384 * 4
|
||||
mssEnviHdr.Bands = 1
|
||||
lw.ws[MSS_HDR].w.Write([]byte(mssEnviHdr.String()))
|
||||
var head AuxFrameHead
|
||||
head.Decode(data[i : i+24])
|
||||
head.SaveXlsx(row)
|
||||
|
||||
// 帧头+辅助数据
|
||||
if len(header)/24 < len(ebAux)/128 || len(ebAux)/128 != len(platAux)/512 {
|
||||
fmt.Println("aux data length:", len(header)/24, len(ebAux)/128, len(platAux)/512)
|
||||
return errors.New("aux data length is not equal")
|
||||
}
|
||||
var box AuxFocalBox
|
||||
box.Decode(data[i+24 : i+24+128])
|
||||
box.SaveXlsx(row)
|
||||
|
||||
auxRows := len(header) / 24
|
||||
for i := 0; i < auxRows; i++ {
|
||||
lw.ws[AUX].w.Write(header[i*24 : (i+1)*24])
|
||||
lw.ws[AUX].w.Write(ebAux[i*128 : (i+1)*128])
|
||||
lw.ws[AUX].w.Write(platAux[i*512 : (i+1)*512])
|
||||
var plat AuxPlatform
|
||||
plat.Decode(data[i+24+128 : i+24+128+512])
|
||||
box.SaveXlsx(row)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Extractor) quanlityAnalysis(data []byte) {
|
||||
// 数据质量分析
|
||||
fimg, _ := os.Create("demo/temp/" + e.params.DataId + "/aux.txt")
|
||||
defer fimg.Close()
|
||||
fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n")
|
||||
|
||||
var startAuxLine bool
|
||||
var preSN uint32
|
||||
for i := 0; i < len(data); {
|
||||
afh := &AuxFrameHead{}
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Errorf("invalid frame head of original raw data i: %v, len: %v", i, len(data))
|
||||
return
|
||||
}
|
||||
|
||||
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), int64(afh.TimeSecFrac)*1000)
|
||||
|
||||
utcTime := binary.BigEndian.Uint32(data[i+32 : i+36])
|
||||
tAux := time.Unix(int64(utcTime+uint32(ReferenceTime2000)), 0)
|
||||
|
||||
startAuxLine = math.Abs(float64(utcTime)-float64(afh.TimeSec)) < 30
|
||||
if startAuxLine {
|
||||
fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n",
|
||||
i,
|
||||
afh.SerialNo,
|
||||
afh.FileNo,
|
||||
t.String(),
|
||||
tAux.String(),
|
||||
))
|
||||
|
||||
if afh.SerialNo-preSN != 16 && preSN != 0 {
|
||||
log.Println("serial number not continuous", afh.SerialNo, preSN)
|
||||
}
|
||||
preSN = afh.SerialNo
|
||||
}
|
||||
|
||||
i += afh.RowLength
|
||||
}
|
||||
}
|
||||
|
||||
// 裁剪图像数据,只保留有效数据
|
||||
func (e *Extractor) trimImgRawData(data []byte) ([]byte, *AuxFrameHead) {
|
||||
var start, end int
|
||||
afh := &AuxFrameHead{}
|
||||
// 将中心辅助数据时间合理的帧作为第一帧
|
||||
var startAuxLine bool
|
||||
for i := 0; i < len(data); {
|
||||
// 解析帧
|
||||
if i+24 > len(data) {
|
||||
log.Info("length of original image frame head is not engough: ", len(data)-i)
|
||||
break
|
||||
}
|
||||
|
||||
if data[i] == 0xD1 && data[i+1] == 0x5B && data[i+2] == 0xD1 && data[i+3] == 0x5B {
|
||||
log.Debug("find package head: 0xD15BD15B")
|
||||
} else {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Debugf("invalid frame head of original raw data %v", i)
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
utcTime := binary.BigEndian.Uint32(data[i+32 : i+36]) // 相对于2000年的秒数
|
||||
startAuxLine = math.Abs(float64(utcTime)-float64(afh.TimeSec)) < 30 // 时间差小于30秒认为是有效数据
|
||||
if !startAuxLine {
|
||||
i += afh.RowLength
|
||||
} else {
|
||||
start = i
|
||||
nLen := (len(data) - i - 1)
|
||||
nLen = nLen - nLen%(afh.RowLength*16)
|
||||
end = i + nLen
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return data[start:end], afh
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/k0kubun/pp/v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tealeg/xlsx"
|
||||
)
|
||||
|
||||
// 卫星时间起点 北京时间 2000-01-01 20:00:00
|
||||
@@ -140,6 +141,10 @@ func (ab AuxFocalBox) PGAGainValue() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (ab AuxFocalBox) SaveXlsx(row *xlsx.Row) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Extractor) ParseAuxEBox(auxfile string) ([]*AuxFocalBox, error) {
|
||||
data, err := os.ReadFile(auxfile)
|
||||
if err != nil {
|
||||
|
||||
436
extract/aux_elements.go
Normal file
436
extract/aux_elements.go
Normal file
@@ -0,0 +1,436 @@
|
||||
package extract
|
||||
|
||||
import "github.com/tealeg/xlsx"
|
||||
|
||||
func createAuxXlxs(fname string) error {
|
||||
nwb := xlsx.NewFile()
|
||||
sheet, err := nwb.AddSheet("辅助数据")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
row := sheet.AddRow()
|
||||
for _, header := range AuxHeader {
|
||||
cell := row.AddCell()
|
||||
cell.SetString(header)
|
||||
}
|
||||
return nwb.Save(fname)
|
||||
}
|
||||
|
||||
var AuxHeader = []string{
|
||||
"包头信息",
|
||||
"填充位",
|
||||
"帧头信息",
|
||||
"当前图像模式",
|
||||
"B4谱状态",
|
||||
"B3谱状态",
|
||||
"B2谱状态",
|
||||
"B1谱状态",
|
||||
"全色状态",
|
||||
"当前行流水号",
|
||||
"时间秒",
|
||||
"秒小数",
|
||||
"文件号",
|
||||
"执行行转移时间",
|
||||
"Trainingdone",
|
||||
"工作模式",
|
||||
"积分方向",
|
||||
"PGA增益",
|
||||
"P谱段积分级数",
|
||||
"B1积分级数",
|
||||
"B2积分级数",
|
||||
"B3积分级数",
|
||||
"B4积分级数",
|
||||
"秒脉冲状态",
|
||||
"保留",
|
||||
"暗场偏置",
|
||||
"全色开窗地址",
|
||||
"多光谱1开窗地址",
|
||||
"多光谱2开窗地址",
|
||||
"多光谱3开窗地址",
|
||||
"多光谱4开窗地址",
|
||||
"面阵模式Linetime时钟周期数",
|
||||
"面阵模式开窗地址",
|
||||
"面阵模式开窗大小",
|
||||
"面阵曝光时间粗调EXP_C",
|
||||
"面阵曝光时间精调EXP_F",
|
||||
"面阵模式最小读出行",
|
||||
"硬盘1温度",
|
||||
"硬盘2温度",
|
||||
"保留",
|
||||
"传感器温度",
|
||||
"FPGA逻辑版本号",
|
||||
"工作模式",
|
||||
"原始盘可用存储容量",
|
||||
"压缩盘可用存储容量",
|
||||
"原始盘状态",
|
||||
"原始盘Host初始化状态",
|
||||
"原始盘SATA控制器状态",
|
||||
"原始盘SATA错误计数",
|
||||
"压缩盘状态",
|
||||
"压缩盘Host初始化状态",
|
||||
"压缩盘SATA控制器状态",
|
||||
"压缩盘SATA错误计数",
|
||||
"保留",
|
||||
"DDR初始化状态",
|
||||
"原始图像硬盘状态",
|
||||
"压缩数据硬盘状态",
|
||||
"硬盘1读写状态",
|
||||
"硬盘2读写状态",
|
||||
"硬盘1初始化状态",
|
||||
"硬盘2初始化状态",
|
||||
"保留",
|
||||
"保留",
|
||||
"硬盘1禁用标志",
|
||||
"硬盘2禁用标志",
|
||||
"保留",
|
||||
"B2数据移位",
|
||||
"B1数据移位",
|
||||
"B4数据移位",
|
||||
"B3数据移位",
|
||||
"指令计数",
|
||||
"最后一条指令编码",
|
||||
"指令接收状态",
|
||||
"错误指令计数",
|
||||
"错误指令帧编号",
|
||||
"保留",
|
||||
"传感器数字电路温度",
|
||||
"卫星UTC时间秒",
|
||||
"卫星复波道标志位",
|
||||
"卫星秒小数",
|
||||
"定姿四元数(J2000)q0",
|
||||
"定姿四元数(J2000)q1",
|
||||
"定姿四元数(J2000)q2",
|
||||
"定姿四元数(J2000)q3",
|
||||
"本体相对轨道四元数矢部q1",
|
||||
"本体相对轨道四元数矢部q2",
|
||||
"本体相对轨道四元数矢部q3",
|
||||
"轨道相对惯性系四元数矢部q1",
|
||||
"轨道相对惯性系四元数矢部q2",
|
||||
"轨道相对惯性系四元数矢部q3",
|
||||
"本体相对轨道姿态角1",
|
||||
"本体相对轨道姿态角2",
|
||||
"本体相对轨道姿态角3",
|
||||
"本体相对轨道角速度1",
|
||||
"本体相对轨道角速度2",
|
||||
"本体相对轨道角速度3",
|
||||
"模式运行时间",
|
||||
"姿控调用周期",
|
||||
"姿轨控部件使用标志",
|
||||
"姿轨控算法执行标记",
|
||||
"偏差四元数q1",
|
||||
"偏差四元数q2",
|
||||
"偏差四元数q3",
|
||||
"偏差角速度1",
|
||||
"偏差角速度2",
|
||||
"偏差角速度3",
|
||||
"X飞轮估计摩擦力矩",
|
||||
"Y飞轮估计摩擦力矩",
|
||||
"Z飞轮估计摩擦力矩",
|
||||
"三轴陀螺X轴角速度漂移估计",
|
||||
"三轴陀螺Y轴角速度漂移估计",
|
||||
"三轴陀螺Z轴角速度漂移估计",
|
||||
"三轴角速度卡尔曼漂移X",
|
||||
"三轴角速度卡尔曼漂移Y",
|
||||
"三轴角速度卡尔曼漂移Z",
|
||||
"X轴估计环境干扰力矩",
|
||||
"Y轴估计环境干扰力矩",
|
||||
"Z轴估计环境干扰力矩",
|
||||
"X轴计算飞轮控制力矩",
|
||||
"Y轴计算飞轮控制力矩",
|
||||
"Z轴计算飞轮控制力矩",
|
||||
"期望四元数矢部1",
|
||||
"期望四元数矢部2",
|
||||
"期望四元数矢部3",
|
||||
"期望角速度1",
|
||||
"期望角速度2",
|
||||
"期望角速度3",
|
||||
"计算当前J2000位置X",
|
||||
"计算当前J2000位置Y",
|
||||
"计算当前J2000位置Z",
|
||||
"计算当前J2000速度X",
|
||||
"计算当前J2000速度Y",
|
||||
"计算当前J2000速度Z",
|
||||
"计算当前84位置X",
|
||||
"计算当前84位置Y",
|
||||
"计算当前84位置Z",
|
||||
"计算当前84速度X",
|
||||
"计算当前84速度Y",
|
||||
"计算当前84速度Z",
|
||||
"偏流角",
|
||||
"数传点经度",
|
||||
"数传点纬度",
|
||||
"数传点地程高",
|
||||
"定姿方式标志1",
|
||||
"定姿方式标志2",
|
||||
"定姿方式标志3",
|
||||
"X飞轮期望转速",
|
||||
"Y飞轮期望转速",
|
||||
"Z飞轮期望转速",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"锂电池温度",
|
||||
"相机主镜温度",
|
||||
"相机次镜温度",
|
||||
"推进模块温度",
|
||||
"负X侧相机桁架杆温度",
|
||||
"正X正Y侧相机桁架杆温度",
|
||||
"正X负Y侧相机桁架杆温度",
|
||||
"正X侧相机支撑背板温度",
|
||||
"负X侧相机支撑背板温度",
|
||||
"星敏支架温度",
|
||||
"成像电箱温度",
|
||||
"正Y帆板温度",
|
||||
"电源下位机温度",
|
||||
"配电热控驱动温度",
|
||||
"电源控制器温度",
|
||||
"数字太阳敏矢量数据有效位",
|
||||
"数字太阳敏矢量数据X",
|
||||
"数字太阳敏矢量数据Y",
|
||||
"数字太阳敏位置X1",
|
||||
"数字太阳敏位置X2",
|
||||
"数字太阳敏位置Y1",
|
||||
"数字太阳敏位置Y2",
|
||||
"太阳敏温度",
|
||||
"数字太阳敏当前正在使用的阈值(源码)",
|
||||
"数字太阳敏当前正在使用的增益",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"错误码计数",
|
||||
"单粒子错误计数",
|
||||
"配电错误码1",
|
||||
"配电错误码2",
|
||||
"配电错误码3",
|
||||
"配电错误码4",
|
||||
"配电错误码5",
|
||||
"GPS天内秒",
|
||||
"GPSUTC时间累计秒",
|
||||
"太阳阵电流",
|
||||
"母线电流",
|
||||
"负载电流",
|
||||
"蓄电池电压",
|
||||
"电源母线电压",
|
||||
"CPU5.2V电压遥测值",
|
||||
"5.2V配电电压遥测值",
|
||||
"保留",
|
||||
"蓄电池组当前电量",
|
||||
"模式运行时间秒",
|
||||
"卫星现运行模式",
|
||||
"组合业务标识",
|
||||
"当前业务状态",
|
||||
"中心机指令接收总计数",
|
||||
"中心机错误指令计数",
|
||||
"执行指令所在分系统",
|
||||
"执行指令的指令代码",
|
||||
"执行延时指令总计数",
|
||||
"当前延时指令计数",
|
||||
"执行延时指令所在分系统",
|
||||
"执行延时指令的指令代码",
|
||||
"当前延时业务计数",
|
||||
"成功执行业务计数",
|
||||
"异常中止业务计数",
|
||||
"指令执行状态",
|
||||
"业务异常中止状态",
|
||||
"测控数传一体机通信状态",
|
||||
"保留",
|
||||
"北斗短报文通信状态",
|
||||
"GPS接收机通信状态",
|
||||
"数字太阳敏通信状态",
|
||||
"星敏1通信状态",
|
||||
"星敏2通信状态",
|
||||
"光纤陀螺通信状态",
|
||||
"MEMS陀螺通信状态",
|
||||
"飞轮1通信状态",
|
||||
"飞轮2通信状态",
|
||||
"飞轮3通信状态",
|
||||
"飞轮4通信状态",
|
||||
"智能载荷通信状态",
|
||||
"保留",
|
||||
"保留",
|
||||
"电磁阀开关状态",
|
||||
"业务保存状态",
|
||||
"卫星类型标识",
|
||||
"卫星序号标识",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"锂电池加热器通断状态",
|
||||
"相机主镜加热器通断状态",
|
||||
"相机次镜加热器通断状态",
|
||||
"推进模块加热器通断状态",
|
||||
"相机负X侧桁架杆加热器通断状态",
|
||||
"成像电箱加热器通断状态",
|
||||
"相机正X正Y侧桁架杆加热器通断状态",
|
||||
"相机正X负Y侧桁架杆加热器通断状态",
|
||||
"相机正X侧支撑背板加热器通断状态",
|
||||
"相机负X侧支撑背板加热器通断状态",
|
||||
"星敏支架加热器通断状态",
|
||||
"保留",
|
||||
"温度修正系数校验状态",
|
||||
"电源下位机广播帧监视功能",
|
||||
"当前控温码表",
|
||||
"默认控温码表",
|
||||
"飞轮1电源供电状态",
|
||||
"飞轮2电源供电状态",
|
||||
"飞轮3电源供电状态",
|
||||
"SADA1电源供电状态",
|
||||
"SADA2电源供电状态",
|
||||
"测控数传电源供电状态",
|
||||
"保留",
|
||||
"保留",
|
||||
"北斗短报文供电状态",
|
||||
"推进电源供电状态",
|
||||
"焦面电源供电状态",
|
||||
"飞轮4电源供电状态",
|
||||
"星敏1电源供电状态",
|
||||
"星敏2电源供电状态",
|
||||
"数字太阳敏电源供电状态",
|
||||
"导航电源供电状态",
|
||||
"三轴光纤陀螺电源供电状态",
|
||||
"MEMS陀螺电源供电状态",
|
||||
"热控正线状态",
|
||||
"热控1状态",
|
||||
"热控2状态",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"锂电池加热器控温模式",
|
||||
"相机主镜加热器控温模式",
|
||||
"相机次镜加热器控温模式",
|
||||
"推进模块加热器控温模式",
|
||||
"相机负X侧桁架杆加热器控温模式",
|
||||
"相机正X正Y侧桁架杆加热器控温模式",
|
||||
"相机正X负Y侧桁架杆加热器控温模式",
|
||||
"相机正X侧支撑背板加热器控温模式",
|
||||
"相机负X侧支撑背板加热器控温模式",
|
||||
"星敏支架加热器控温模式",
|
||||
"成像电箱加热器控温模式",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"保留",
|
||||
"接收机时间来源",
|
||||
"定位模式",
|
||||
"轨道数据有效标示",
|
||||
"主备机标志",
|
||||
"PPS状态",
|
||||
"GPS最高信噪比",
|
||||
"BD最高信噪比",
|
||||
"参与定位的GPS导航星数",
|
||||
"参与定位的BD导航星数",
|
||||
"GPS几何精度因子",
|
||||
"GPS连续工作时间",
|
||||
"保留",
|
||||
"保留",
|
||||
"WGS-84系X位置",
|
||||
"WGS-84系Y位置",
|
||||
"WGS-84系Z位置",
|
||||
"WGS-84系X速度",
|
||||
"WGS-84系Y速度",
|
||||
"WGS-84系Z速度",
|
||||
"J2000系X位置",
|
||||
"J2000系Y位置",
|
||||
"J2000系Z位置",
|
||||
"J2000系X速度",
|
||||
"J2000系Y速度",
|
||||
"J2000系Z速度",
|
||||
"三轴光纤陀螺X轴角速度",
|
||||
"三轴光纤陀螺Y轴角速度",
|
||||
"三轴光纤陀螺Z轴角速度",
|
||||
"三轴光纤陀螺X轴角速度(1)",
|
||||
"三轴光纤陀螺Y轴角速度(1)",
|
||||
"三轴光纤陀螺Z轴角速度(1)",
|
||||
"星敏AUTC时间",
|
||||
"星敏AUTC秒小数",
|
||||
"星敏A四元数q1",
|
||||
"星敏A四元数q2",
|
||||
"星敏A四元数q3",
|
||||
"星敏A四元数q4",
|
||||
"星敏A曝光时间",
|
||||
"星敏A阈值",
|
||||
"星敏A背景值",
|
||||
"星敏A上电进入boot标志",
|
||||
"星敏AEDAC打开标志",
|
||||
"星敏A程序版本",
|
||||
"星敏A四元数滤波标志",
|
||||
"星敏A系统内部工作进程代号",
|
||||
"星敏A系统工作模式",
|
||||
"星敏A提取星数",
|
||||
"星敏A四元数有效时导航星数",
|
||||
"星敏A图像增益",
|
||||
"星敏A识别星数",
|
||||
"星敏A打开或者关断外部图像",
|
||||
"星敏A姿态数据有效标志",
|
||||
"星敏A内部软件版本号低3位",
|
||||
"星敏A产品设备编号低5位",
|
||||
"星敏A成像传感器温度",
|
||||
"星敏A在轨EDAC错误计数",
|
||||
"星敏A图像帧号",
|
||||
"星敏A四星寻找阈值",
|
||||
"星敏A跟踪阈值",
|
||||
"星敏ASAA阈值",
|
||||
"星敏ASAA工作模式",
|
||||
"星敏A动态模式标志位",
|
||||
"星敏AX方向角速度",
|
||||
"星敏AY方向角速度",
|
||||
"星敏AZ方向角速度",
|
||||
"星敏A星点阈值自适应功能",
|
||||
"保留",
|
||||
"星敏A速率质量",
|
||||
"星敏BUTC时间",
|
||||
"星敏BUTC秒小数",
|
||||
"星敏B四元数q1",
|
||||
"星敏B四元数q2",
|
||||
"星敏B四元数q3",
|
||||
"星敏B四元数q4",
|
||||
"星敏B曝光时间",
|
||||
"星敏B阈值",
|
||||
"星敏B背景值",
|
||||
"星敏B上电进入boot标志",
|
||||
"星敏BEDAC打开标志",
|
||||
"星敏B程序版本",
|
||||
"星敏B四元数滤波标志",
|
||||
"星敏B系统内部工作进程代号",
|
||||
"星敏B系统工作模式",
|
||||
"星敏B提取星数",
|
||||
"星敏B四元数有效时导航星数",
|
||||
"星敏B图像增益",
|
||||
"星敏B识别星数",
|
||||
"星敏B打开或者关断外部图像",
|
||||
"星敏B姿态数据有效标志",
|
||||
"星敏B内部软件版本号低3位",
|
||||
"星敏B产品设备编号低5位",
|
||||
"星敏B成像传感器温度",
|
||||
"星敏B在轨EDAC错误计数",
|
||||
"星敏B图像帧号",
|
||||
"星敏B四星寻找阈值",
|
||||
"星敏B跟踪阈值",
|
||||
"星敏BSAA阈值",
|
||||
"星敏BSAA工作模式",
|
||||
"星敏B动态模式标志位",
|
||||
"保留",
|
||||
"飞轮1转速",
|
||||
"飞轮1当前电流",
|
||||
"飞轮2转速",
|
||||
"飞轮2当前电流",
|
||||
"飞轮3转速",
|
||||
"飞轮3当前电流",
|
||||
"飞轮4转速",
|
||||
"飞轮4当前电流",
|
||||
"MEMS陀螺X方向角速度",
|
||||
"MEMS陀螺Y方向角速度",
|
||||
"MEMS陀螺Z方向角速度",
|
||||
"X方向磁场强度",
|
||||
"Y方向磁场强度",
|
||||
"Z方向磁场强度",
|
||||
"输入姿轨控数据UTC时间秒",
|
||||
"输入姿轨控数据时间秒小数",
|
||||
"保留",
|
||||
"校验和",
|
||||
}
|
||||
138
extract/aux_head.go
Normal file
138
extract/aux_head.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package extract
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/tealeg/xlsx"
|
||||
)
|
||||
|
||||
// 每行传感器数据帧头信息长度为24字节
|
||||
type AuxFrameHead struct {
|
||||
PkgHead [4]byte // 包头头标识符,固定为0xD15BD15B
|
||||
FillByte0 byte // 填充字节 0x00
|
||||
FrmHead [6]byte // 帧头标识符,固定为0xEB90EB90EB90
|
||||
// 图像模式
|
||||
// B7 模式标识 000:为线阵模式
|
||||
// B6
|
||||
// B5
|
||||
// B4 B4谱状态 0:不输出1:输出
|
||||
// B3 B3谱状态 0:不输出1:输出
|
||||
// B2 B2谱状态 0:不输出1:输出
|
||||
// B1 B1谱状态 0:不输出1:输出
|
||||
// B0 全色状态 0:不输出1:输出
|
||||
ImgMode byte
|
||||
SerialNo uint32 // 当前流水号
|
||||
TimeSec uint32 // 时间(秒)
|
||||
TimeSecFrac uint32 // 秒小数 量纲:1us/bit,十六进制无符号整型数
|
||||
FileNo uint8 // 文件号
|
||||
|
||||
IsValidFrmHead bool
|
||||
B0 bool
|
||||
B1 bool
|
||||
B2 bool
|
||||
B3 bool
|
||||
B4 bool
|
||||
IsLinerMatrix bool
|
||||
RowLength int
|
||||
}
|
||||
|
||||
func (afh *AuxFrameHead) Decode(data []byte) error {
|
||||
if len(data) < 24 {
|
||||
return errors.New("length of AuxFrameHead is not 24")
|
||||
}
|
||||
|
||||
afh.PkgHead = [4]byte{data[0], data[1], data[2], data[3]}
|
||||
afh.FillByte0 = data[4]
|
||||
afh.FrmHead = [6]byte{data[5], data[6], data[7], data[8], data[9], data[10]}
|
||||
afh.ImgMode = data[11]
|
||||
afh.B0 = (afh.ImgMode&(1<<0) != 0x0)
|
||||
afh.B1 = (afh.ImgMode&(1<<1) != 0x0)
|
||||
afh.B2 = (afh.ImgMode&(1<<2) != 0x0)
|
||||
afh.B3 = (afh.ImgMode&(1<<3) != 0x0)
|
||||
afh.B4 = (afh.ImgMode&(1<<4) != 0x0)
|
||||
afh.IsLinerMatrix = (afh.ImgMode&(1<<5) == 0x0 && afh.ImgMode&(1<<6) == 0x0 && afh.ImgMode&(1<<7) == 0x0)
|
||||
afh.SerialNo = binary.BigEndian.Uint32(data[12:16])
|
||||
afh.TimeSec = binary.BigEndian.Uint32(data[16:20])
|
||||
afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22]))
|
||||
afh.FileNo = data[23]
|
||||
|
||||
afh.RowLength = afh.LengthOfRow()
|
||||
afh.IsValidFrmHead = afh.CheckFrmHead()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 计算一行数据长度:帧头+辅助数据+图像数据
|
||||
func (afh AuxFrameHead) LengthOfRow() int {
|
||||
if !afh.IsLinerMatrix {
|
||||
return 14344
|
||||
}
|
||||
|
||||
length := 64 // 帧头+辅助数据长度
|
||||
if afh.B0 {
|
||||
length += 19040
|
||||
}
|
||||
if afh.B1 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B2 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B3 {
|
||||
length += 1192
|
||||
}
|
||||
if afh.B4 {
|
||||
length += 1192
|
||||
}
|
||||
|
||||
return length
|
||||
}
|
||||
|
||||
func (afh AuxFrameHead) CheckFrmHead() bool {
|
||||
if afh.FrmHead[0] == 0xEB && afh.FrmHead[1] == 0x90 &&
|
||||
afh.FrmHead[2] == 0xEB && afh.FrmHead[3] == 0x90 &&
|
||||
afh.FrmHead[4] == 0xEB && afh.FrmHead[5] == 0x90 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (afh AuxFrameHead) SaveXlsx(row *xlsx.Row) error {
|
||||
values := []string{
|
||||
fmt.Sprintf("0x%x", afh.PkgHead),
|
||||
"",
|
||||
fmt.Sprintf("0x%x", afh.FrmHead),
|
||||
afh.ImageMode(),
|
||||
afh.BandStatus(afh.B4),
|
||||
afh.BandStatus(afh.B3),
|
||||
afh.BandStatus(afh.B2),
|
||||
afh.BandStatus(afh.B1),
|
||||
afh.BandStatus(afh.B0),
|
||||
fmt.Sprintf("%d", afh.SerialNo),
|
||||
fmt.Sprintf("%d", afh.TimeSec),
|
||||
fmt.Sprintf("%d", afh.TimeSecFrac),
|
||||
fmt.Sprintf("%d", afh.FileNo),
|
||||
}
|
||||
|
||||
for _, v := range values {
|
||||
row.AddCell().SetString(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (afh AuxFrameHead) ImageMode() string {
|
||||
if afh.IsLinerMatrix {
|
||||
return "线阵模式"
|
||||
}
|
||||
return "面阵模式"
|
||||
}
|
||||
|
||||
func (afh AuxFrameHead) BandStatus(b bool) string {
|
||||
if b {
|
||||
return "输出"
|
||||
}
|
||||
return "不输出"
|
||||
}
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/k0kubun/pp/v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tealeg/xlsx"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"starwiz.cn/sjy01/preprocessing/calculator"
|
||||
)
|
||||
@@ -129,7 +130,7 @@ type AuxPlatform struct {
|
||||
SS1_ExtenalImage bool // [407.(1)] 星敏1外部图像标志位 0x01:外部图像;0x00:关闭
|
||||
SS1_AttitudeActive bool // [407.(0)] 星敏1姿态有效标志位 0x01:激活;0x00:关闭
|
||||
SS1_ImgFrmNo uint32 // [411-413] 星敏1图像帧号
|
||||
SS1_XAV float64 // [417-418] 星敏1X方向角速度 单位:2-11 °/s
|
||||
SS1_XAV float64 // [417-418] 星敏1X方向角速度 单位:2e-11 °/s
|
||||
SS1_YAV float64 // [419-420]
|
||||
SS1_ZAV float64 // [421-422]
|
||||
SS2_UTCTime uint32 // [424-427] 星敏2 UTC时间
|
||||
@@ -170,7 +171,7 @@ type AuxPlatform struct {
|
||||
CheckSum byte // [512] 校验和
|
||||
}
|
||||
|
||||
func (ap *AuxPlatform) Parse(data []byte) error {
|
||||
func (ap *AuxPlatform) Decode(data []byte) error {
|
||||
if len(data) < 512 {
|
||||
return ErrAuxPlatformDataLen
|
||||
}
|
||||
@@ -337,19 +338,23 @@ func (ap AuxPlatform) Print() {
|
||||
pp.Println(ap)
|
||||
}
|
||||
|
||||
func (ap AuxPlatform) SaveXlsx(row *xlsx.Row) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extractor 辅助数据提取器
|
||||
// auxfile 辅助数据文件路径
|
||||
func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
||||
data, err := os.ReadFile(auxfile)
|
||||
if err != nil {
|
||||
logrus.Println("read aux data from", auxfile, "error:", err.Error())
|
||||
log.Println("read aux data from", auxfile, "error:", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var aps []*AuxPlatform
|
||||
for i := 0; i < len(data); i += 24 + 128 + 512 {
|
||||
ap := AuxPlatform{}
|
||||
if err := ap.Parse(data[i+24+128 : i+24+128+512]); err != nil {
|
||||
if err := ap.Decode(data[i+24+128 : i+24+128+512]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -387,7 +392,7 @@ func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
||||
func (e *Extractor) ParseAuxPlatformWithHead(auxfile string) ([]*AuxPlatform, error) {
|
||||
data, err := os.ReadFile(auxfile)
|
||||
if err != nil {
|
||||
logrus.Println("read aux data from", auxfile, "error:", err.Error())
|
||||
log.Println("read aux data from", auxfile, "error:", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
package extract
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// 定义常数
|
||||
const (
|
||||
GM = 3.986004418e14 // 地球引力常数(m^3/s^2)
|
||||
Re = 6378137.0 // 地球半径(m)
|
||||
)
|
||||
|
||||
// 四元数
|
||||
type Quaternion struct {
|
||||
w, x, y, z float64
|
||||
}
|
||||
|
||||
// 矢量
|
||||
type Vector3 struct {
|
||||
x, y, z float64
|
||||
}
|
||||
|
||||
// 计算轨道参数
|
||||
func calculateOrbitalParameters(position, velocity Vector3) (float64, float64, float64, float64, float64) {
|
||||
r := math.Sqrt(position.x*position.x + position.y*position.y + position.z*position.z)
|
||||
v := math.Sqrt(velocity.x*velocity.x + velocity.y*velocity.y + velocity.z*velocity.z)
|
||||
|
||||
// 计算轨道参数
|
||||
energy := 0.5*v*v - GM/r // 比能
|
||||
a := -GM / (2 * energy) // 轨道半长轴
|
||||
e := math.Sqrt(1 - (math.Pow(math.Sqrt(math.Pow(position.x*velocity.y-position.y*velocity.x, 2)+
|
||||
math.Pow(position.y*velocity.z-position.z*velocity.y, 2)+
|
||||
math.Pow(position.z*velocity.x-position.x*velocity.z, 2)), 2) / (GM * a)))
|
||||
i := math.Acos(position.z / r) // 轨道倾角
|
||||
Omega := math.Atan2(position.x, -position.y) // 升交点赤经
|
||||
omega := math.Atan2(position.z*velocity.x-position.x*velocity.z, position.x*velocity.y-position.y*velocity.x) // 升交点赤纬
|
||||
return a, e, i * 180 / math.Pi, Omega * 180 / math.Pi, omega * 180 / math.Pi
|
||||
}
|
||||
|
||||
// 四元数到旋转矩阵
|
||||
func quaternionToRotationMatrix(q Quaternion) [3][3]float64 {
|
||||
w, x, y, z := q.w, q.x, q.y, q.z
|
||||
return [3][3]float64{
|
||||
{1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w},
|
||||
{2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w},
|
||||
{2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x*x - 2*y*y},
|
||||
}
|
||||
}
|
||||
|
||||
// 向量加法
|
||||
func add(v1, v2 Vector3) Vector3 {
|
||||
return Vector3{v1.x + v2.x, v1.y + v2.y, v1.z + v2.z}
|
||||
}
|
||||
|
||||
// 向量数乘
|
||||
func scale(v Vector3, c float64) Vector3 {
|
||||
return Vector3{v.x * c, v.y * c, v.z * c}
|
||||
}
|
||||
|
||||
// 矩阵乘法
|
||||
func matrixMult(m [3][3]float64, v Vector3) Vector3 {
|
||||
return Vector3{
|
||||
m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z,
|
||||
m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z,
|
||||
m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z,
|
||||
}
|
||||
}
|
||||
|
||||
// 计算图像位置
|
||||
func calculateImagePosition(roll, pitch, yaw float64, quat Quaternion, satellitePos, satelliteVel Vector3) (float64, float64) {
|
||||
// 将角度转换为弧度
|
||||
roll = roll * math.Pi / 180
|
||||
pitch = pitch * math.Pi / 180
|
||||
yaw = yaw * math.Pi / 180
|
||||
|
||||
// 构造旋转矩阵
|
||||
R := quaternionToRotationMatrix(quat)
|
||||
// 传感器坐标系中的Z轴向量
|
||||
sensorZ := Vector3{0, 0, 1}
|
||||
// 将Z轴向量通过旋转矩阵转换到卫星坐标系中
|
||||
lineOfSight := matrixMult(R, sensorZ)
|
||||
|
||||
// 计算交点经纬度
|
||||
lat := math.Asin(lineOfSight.z) * 180 / math.Pi
|
||||
lon := math.Atan2(lineOfSight.y, lineOfSight.x) * 180 / math.Pi
|
||||
|
||||
return lat, lon
|
||||
}
|
||||
|
||||
func Calculate(satellitePos, satelliteVel Vector3, quat Quaternion) {
|
||||
// 假设一些已知数据
|
||||
// satellitePos := Vector3{x: 7000e3, y: 0, z: 0} // 假设一个简单的地心坐标位置
|
||||
// satelliteVel := Vector3{x: 0, y: 7.5e3, z: 0} // 假设一个简单的速度
|
||||
// quat := Quaternion{w: 0.7071, x: 0.7071, y: 0, z: 0} // 假设一个简单的四元数
|
||||
roll := 0.0
|
||||
pitch := 0.0
|
||||
yaw := 0.0
|
||||
|
||||
// 计算轨道参数
|
||||
a, e, i, Omega, omega := calculateOrbitalParameters(satellitePos, satelliteVel)
|
||||
|
||||
// 打印轨道参数
|
||||
fmt.Println("轨道参数:")
|
||||
fmt.Printf("轨道半长轴 (a): %.2f m\n", a)
|
||||
fmt.Printf("偏心率 (e): %.6f\n", e)
|
||||
fmt.Printf("轨道倾角 (i): %.2f 度\n", i)
|
||||
fmt.Printf("升交点赤经 (Ω): %.2f 度\n", Omega)
|
||||
fmt.Printf("近地点幅角 (ω): %.2f 度\n", omega)
|
||||
|
||||
// 计算图像位置
|
||||
lat, lon := calculateImagePosition(roll, pitch, yaw, quat, satellitePos, satelliteVel)
|
||||
fmt.Printf("\n图像位置:\n纬度: %.6f\n经度: %.6f\n", lat, lon)
|
||||
}
|
||||
@@ -4,18 +4,9 @@ import (
|
||||
"bytes"
|
||||
"html"
|
||||
|
||||
"io"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type BSQWriter struct {
|
||||
filepath string
|
||||
fio *os.File
|
||||
w io.Writer
|
||||
content *EnviHdr
|
||||
}
|
||||
|
||||
var HDRTemplate = `ENVI
|
||||
description = {
|
||||
File Imported into ENVI.}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package extract
|
||||
289
extract/seperate.go
Normal file
289
extract/seperate.go
Normal file
@@ -0,0 +1,289 @@
|
||||
package extract
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
|
||||
func (e *Extractor) SeprateAuxAndImgData(dataFile string, segmentIndex int) error {
|
||||
// 打开传输帧文件 - 一次读入内存
|
||||
data, err := os.ReadFile(dataFile)
|
||||
if err != nil {
|
||||
log.Println("read data from", dataFile, "error:", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("seprate aux and img data from", dataFile)
|
||||
|
||||
dataLen := len(data)
|
||||
log.Info("length of original data: ", dataLen)
|
||||
var firstFrmHead *AuxFrameHead
|
||||
data, firstFrmHead = e.trimImgRawData(data)
|
||||
dataLen = len(data)
|
||||
log.Info("after trim,length of data: ", dataLen)
|
||||
e.quanlityAnalysis(data)
|
||||
|
||||
outputDir := e.params.OutputPath
|
||||
name := strings.Join([]string{
|
||||
e.params.Satellite,
|
||||
"PMS",
|
||||
time.Unix(int64(firstFrmHead.TimeSec)+int64(ReferenceTime2000),
|
||||
int64(firstFrmHead.TimeSecFrac)*1000).
|
||||
Format("20060102_150405"),
|
||||
e.params.DataId,
|
||||
fmt.Sprintf("%03d", firstFrmHead.FileNo),
|
||||
}, "_")
|
||||
|
||||
lw := newL0Writer(outputDir, name)
|
||||
defer lw.Close()
|
||||
|
||||
var panEnviHdr, mssEnviHdr EnviHdr
|
||||
|
||||
var afh AuxFrameHead
|
||||
|
||||
msdata := make([][]byte, 4)
|
||||
var header []byte
|
||||
var ebAux []byte
|
||||
var platAux []byte
|
||||
|
||||
for i := 0; i < dataLen; {
|
||||
if i+4 > dataLen {
|
||||
logrus.Println("end of data, dataLen:", dataLen, "i:", i)
|
||||
break
|
||||
}
|
||||
|
||||
// 包头
|
||||
if data[i] == 0xD1 && data[i+1] == 0x5B && data[i+2] == 0xD1 && data[i+3] == 0x5B {
|
||||
log.Debug("find package head: 0xD15BD15B")
|
||||
} else {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析帧
|
||||
if i+24 > dataLen {
|
||||
log.Info("length of frame head is not engough for frame head")
|
||||
break
|
||||
}
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Info("invalid frame head of original raw data")
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
// 目前只支持线阵模式
|
||||
if !afh.IsLinerMatrix {
|
||||
log.Error("not liner matrix mode, only support liner matrix mode")
|
||||
break
|
||||
}
|
||||
|
||||
// 读取一行数据 data[i : i+afh.RowLength]
|
||||
if i+afh.RowLength > dataLen {
|
||||
log.Infof("length of image row data %v is not enough: %v", dataLen-i, afh.RowLength)
|
||||
break
|
||||
}
|
||||
|
||||
auxTime := binary.BigEndian.Uint32(data[i+32 : i+36])
|
||||
if math.Abs(float64(auxTime)-float64(afh.TimeSec)) < 30 {
|
||||
header = append(header, data[i:i+24]...)
|
||||
}
|
||||
// 存储辅助数据到临时文件
|
||||
dataIndex := i + 24
|
||||
// lw.ws[EB_AUX].w.Write(data[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据
|
||||
ebAux = append(ebAux, data[dataIndex:dataIndex+8]...)
|
||||
dataIndex += 8
|
||||
// lw.ws[PLAT_AUX].w.Write(data[dataIndex : dataIndex+32]) // 32字节中心机辅助数据
|
||||
platAux = append(platAux, data[dataIndex:dataIndex+32]...)
|
||||
dataIndex += 32
|
||||
|
||||
// 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件
|
||||
if afh.B0 {
|
||||
// wpan.Write(data[dataIndex : dataIndex+19040])
|
||||
write16bPixelLittleEndian(lw.ws[PAN_RAW].w, data[dataIndex:dataIndex+19040])
|
||||
dataIndex += 19040
|
||||
panEnviHdr.Lines += 1
|
||||
}
|
||||
|
||||
if afh.B1 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[0] = append(msdata[0], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
mssEnviHdr.Lines += 1
|
||||
}
|
||||
if afh.B2 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[1] = append(msdata[1], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
if afh.B3 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[2] = append(msdata[2], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
if afh.B4 {
|
||||
// write16bPixelLittleEndian(wmss, data[dataIndex:dataIndex+1192])
|
||||
msdata[3] = append(msdata[3], data[dataIndex:dataIndex+1192]...)
|
||||
dataIndex += 1192
|
||||
}
|
||||
i = dataIndex // 完成一行数据解析
|
||||
}
|
||||
|
||||
// var bands = 0
|
||||
// for i := 0; i < 4; i++ {
|
||||
// if len(msdata[i]) > 0 {
|
||||
// log.Println("write mss data of band B", i+1)
|
||||
// _, err := write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[i])
|
||||
// if err != nil {
|
||||
// log.Error("write mss data error:", err.Error())
|
||||
// }
|
||||
// bands += 1
|
||||
// }
|
||||
// }
|
||||
|
||||
if len(msdata[0]) != len(msdata[1]) || len(msdata[2]) != len(msdata[3]) {
|
||||
log.Error("mss data of bands B1-B4 are not equal")
|
||||
return errors.New("mss data of bands B1-B4 are not equal")
|
||||
}
|
||||
|
||||
mssRowLen := 1192 * 4
|
||||
for i := 0; i < len(msdata[0]); i += mssRowLen {
|
||||
var err error
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[0][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 1 data error:", err.Error())
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[1][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 2 data error:", err.Error())
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[2][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 3 data error:", err.Error())
|
||||
}
|
||||
_, err = write16bPixelLittleEndian(lw.ws[MSS_RAW].w, msdata[3][i:i+mssRowLen])
|
||||
if err != nil {
|
||||
log.Error("write mss 4 data error:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
panEnviHdr.Samples = 9520
|
||||
panEnviHdr.Bands = 1
|
||||
lw.ws[PAN_HDR].w.Write([]byte(panEnviHdr.String()))
|
||||
|
||||
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
|
||||
mssEnviHdr.Samples = 2384 * 4
|
||||
mssEnviHdr.Bands = 1
|
||||
lw.ws[MSS_HDR].w.Write([]byte(mssEnviHdr.String()))
|
||||
|
||||
// 帧头+辅助数据
|
||||
if len(header)/24 < len(ebAux)/128 || len(ebAux)/128 != len(platAux)/512 {
|
||||
fmt.Println("aux data length:", len(header)/24, len(ebAux)/128, len(platAux)/512)
|
||||
return errors.New("aux data length is not equal")
|
||||
}
|
||||
|
||||
auxRows := len(header) / 24
|
||||
for i := 0; i < auxRows; i++ {
|
||||
lw.ws[AUX].w.Write(header[i*24 : (i+1)*24])
|
||||
lw.ws[AUX].w.Write(ebAux[i*128 : (i+1)*128])
|
||||
lw.ws[AUX].w.Write(platAux[i*512 : (i+1)*512])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Extractor) quanlityAnalysis(data []byte) {
|
||||
// 数据质量分析
|
||||
fimg, _ := os.Create("demo/temp/" + e.params.DataId + "/aux.txt")
|
||||
defer fimg.Close()
|
||||
fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n")
|
||||
|
||||
var startAuxLine bool
|
||||
var preSN uint32
|
||||
for i := 0; i < len(data); {
|
||||
afh := &AuxFrameHead{}
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Errorf("invalid frame head of original raw data i: %v, len: %v", i, len(data))
|
||||
return
|
||||
}
|
||||
|
||||
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), int64(afh.TimeSecFrac)*1000)
|
||||
|
||||
utcTime := binary.BigEndian.Uint32(data[i+32 : i+36])
|
||||
tAux := time.Unix(int64(utcTime+uint32(ReferenceTime2000)), 0)
|
||||
|
||||
startAuxLine = math.Abs(float64(utcTime)-float64(afh.TimeSec)) < 30
|
||||
if startAuxLine {
|
||||
fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n",
|
||||
i,
|
||||
afh.SerialNo,
|
||||
afh.FileNo,
|
||||
t.String(),
|
||||
tAux.String(),
|
||||
))
|
||||
|
||||
if afh.SerialNo-preSN != 16 && preSN != 0 {
|
||||
log.Println("serial number not continuous", afh.SerialNo, preSN)
|
||||
}
|
||||
preSN = afh.SerialNo
|
||||
}
|
||||
|
||||
i += afh.RowLength
|
||||
}
|
||||
}
|
||||
|
||||
// 裁剪图像数据,只保留有效数据
|
||||
func (e *Extractor) trimImgRawData(data []byte) ([]byte, *AuxFrameHead) {
|
||||
var start, end int
|
||||
afh := &AuxFrameHead{}
|
||||
// 将中心辅助数据时间合理的帧作为第一帧
|
||||
var startAuxLine bool
|
||||
for i := 0; i < len(data); {
|
||||
// 解析帧
|
||||
if i+24 > len(data) {
|
||||
log.Info("length of original image frame head is not engough: ", len(data)-i)
|
||||
break
|
||||
}
|
||||
|
||||
if data[i] == 0xD1 && data[i+1] == 0x5B && data[i+2] == 0xD1 && data[i+3] == 0x5B {
|
||||
log.Debug("find package head: 0xD15BD15B")
|
||||
} else {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
afh.Decode(data[i : i+24])
|
||||
|
||||
if !afh.IsValidFrmHead {
|
||||
log.Debugf("invalid frame head of original raw data %v", i)
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
utcTime := binary.BigEndian.Uint32(data[i+32 : i+36]) // 相对于2000年的秒数
|
||||
startAuxLine = math.Abs(float64(utcTime)-float64(afh.TimeSec)) < 30 // 时间差小于30秒认为是有效数据
|
||||
if !startAuxLine {
|
||||
i += afh.RowLength
|
||||
} else {
|
||||
start = i
|
||||
nLen := (len(data) - i - 1)
|
||||
nLen = nLen - nLen%(afh.RowLength*16)
|
||||
end = i + nLen
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return data[start:end], afh
|
||||
}
|
||||
3
go.mod
3
go.mod
@@ -4,13 +4,12 @@ go 1.21
|
||||
|
||||
toolchain go1.21.0
|
||||
|
||||
require github.com/twpayne/go-proj/v10 v10.2.0
|
||||
|
||||
require (
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.33.1 // indirect
|
||||
github.com/tealeg/xlsx v1.0.5 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/term v0.20.0 // indirect
|
||||
|
||||
14
go.sum
14
go.sum
@@ -1,7 +1,3 @@
|
||||
github.com/alecthomas/assert/v2 v2.8.0 h1:8b0foWfS2dH6MltxQMPvWdSGN1wE4K1vyab9PGW4qgE=
|
||||
github.com/alecthomas/assert/v2 v2.8.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -24,8 +20,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
@@ -33,6 +27,9 @@ github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/k0kubun/pp/v3 v3.2.0 h1:h33hNTZ9nVFNP3u2Fsgz8JXiF5JINoZfFq4SvKJwNcs=
|
||||
github.com/k0kubun/pp/v3 v3.2.0/go.mod h1:ODtJQbQcIRfAD3N+theGCV1m/CBxweERz2dapdz1EwA=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
||||
@@ -75,8 +72,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/twpayne/go-proj/v10 v10.2.0 h1:EurvRTcUMqsiARMhcF0KDvBjKZeCzJqAPQ0WAbrDFdQ=
|
||||
github.com/twpayne/go-proj/v10 v10.2.0/go.mod h1:BU5zbXY6XmKenoyf+DbIg7joKlKTJM2rEssPMPJZYjY=
|
||||
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
|
||||
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -132,6 +129,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
||||
Reference in New Issue
Block a user