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 (
|
var (
|
||||||
dataId string
|
dataId string
|
||||||
batch bool
|
batch bool
|
||||||
|
output string
|
||||||
)
|
)
|
||||||
|
|
||||||
var extractCmd = &cobra.Command{
|
var extractCmd = &cobra.Command{
|
||||||
@@ -31,7 +32,7 @@ var extractCmd = &cobra.Command{
|
|||||||
} else {
|
} else {
|
||||||
p := &extract.Params{
|
p := &extract.Params{
|
||||||
InputData: fmt.Sprintf("demo/data/%s.dat", dataId),
|
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),
|
TempPath: fmt.Sprintf("demo/temp/%s", dataId),
|
||||||
DataId: dataId,
|
DataId: dataId,
|
||||||
Satellite: "SJY01",
|
Satellite: "SJY01",
|
||||||
@@ -51,16 +52,18 @@ func init() {
|
|||||||
|
|
||||||
extractCmd.Flags().StringVarP(&dataId, "data-id", "d", "051622", "051622")
|
extractCmd.Flags().StringVarP(&dataId, "data-id", "d", "051622", "051622")
|
||||||
extractCmd.Flags().BoolVarP(&batch, "batch", "b", false, "true | false")
|
extractCmd.Flags().BoolVarP(&batch, "batch", "b", false, "true | false")
|
||||||
|
extractCmd.Flags().StringVarP(&output, "out", "o", "demo/output", "demo/output")
|
||||||
}
|
}
|
||||||
|
|
||||||
func params() []*extract.Params {
|
func params() []*extract.Params {
|
||||||
var params []*extract.Params
|
var params []*extract.Params
|
||||||
datas := []string{"051513", "051622",
|
datas := []string{"051622", "051712", "051721",
|
||||||
"051712", "051721", "051821", "051823", "051921", "051922", "Q051723"}
|
"051813", "051821", "051823",
|
||||||
|
"051921", "051922", "052022"}
|
||||||
for _, d := range datas {
|
for _, d := range datas {
|
||||||
params = append(params, &extract.Params{
|
params = append(params, &extract.Params{
|
||||||
InputData: fmt.Sprintf("demo/data/%s.dat", d),
|
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),
|
TempPath: fmt.Sprintf("demo/temp/%s", d),
|
||||||
DataId: d,
|
DataId: d,
|
||||||
Satellite: "SJY01",
|
Satellite: "SJY01",
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ var parseCmd = &cobra.Command{
|
|||||||
e := extract.NewExtractor(¶ms)
|
e := extract.NewExtractor(¶ms)
|
||||||
// p.ParseAuxPlatformWithHead("demo/ref/辅助数据.dat")
|
// p.ParseAuxPlatformWithHead("demo/ref/辅助数据.dat")
|
||||||
fmt.Println("Reference Time: 2000-01-01 12:00:00 UTC, seconds:", extract.Time2000UTCSec())
|
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 {
|
if err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
// p.ParseAuxEBox("demo/output/SJY01_PMS_20240516_101236_051622_096_EB.AUX")
|
// 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
|
package extract
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/tealeg/xlsx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 每行传感器数据帧头信息长度为24字节
|
func (e Extractor) ExtractAux(auxfile, xlsxfile string) error {
|
||||||
type AuxFrameHead struct {
|
if err := createAuxXlxs(xlsxfile); err != nil {
|
||||||
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())
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("seprate aux and img data from", dataFile)
|
wb, err := xlsx.OpenFile(xlsxfile)
|
||||||
|
if err != nil {
|
||||||
dataLen := len(data)
|
panic(err)
|
||||||
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
|
sh := wb.Sheets[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]) {
|
data, err := os.ReadFile(auxfile)
|
||||||
log.Error("mss data of bands B1-B4 are not equal")
|
if err != nil {
|
||||||
return errors.New("mss data of bands B1-B4 are not equal")
|
log.Println("read aux data from", auxfile, "error:", err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mssRowLen := 1192 * 4
|
for i := 0; i < len(data); i += 24 + 128 + 512 {
|
||||||
for i := 0; i < len(msdata[0]); i += mssRowLen {
|
row := sh.AddRow()
|
||||||
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
|
var head AuxFrameHead
|
||||||
panEnviHdr.Bands = 1
|
head.Decode(data[i : i+24])
|
||||||
lw.ws[PAN_HDR].w.Write([]byte(panEnviHdr.String()))
|
head.SaveXlsx(row)
|
||||||
|
|
||||||
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
|
var box AuxFocalBox
|
||||||
mssEnviHdr.Samples = 2384 * 4
|
box.Decode(data[i+24 : i+24+128])
|
||||||
mssEnviHdr.Bands = 1
|
box.SaveXlsx(row)
|
||||||
lw.ws[MSS_HDR].w.Write([]byte(mssEnviHdr.String()))
|
|
||||||
|
|
||||||
// 帧头+辅助数据
|
var plat AuxPlatform
|
||||||
if len(header)/24 < len(ebAux)/128 || len(ebAux)/128 != len(platAux)/512 {
|
plat.Decode(data[i+24+128 : i+24+128+512])
|
||||||
fmt.Println("aux data length:", len(header)/24, len(ebAux)/128, len(platAux)/512)
|
box.SaveXlsx(row)
|
||||||
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
|
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/k0kubun/pp/v3"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/tealeg/xlsx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 卫星时间起点 北京时间 2000-01-01 20:00:00
|
// 卫星时间起点 北京时间 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) {
|
func (e *Extractor) ParseAuxEBox(auxfile string) ([]*AuxFocalBox, error) {
|
||||||
data, err := os.ReadFile(auxfile)
|
data, err := os.ReadFile(auxfile)
|
||||||
if err != nil {
|
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"
|
"time"
|
||||||
|
|
||||||
"github.com/k0kubun/pp/v3"
|
"github.com/k0kubun/pp/v3"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/tealeg/xlsx"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"starwiz.cn/sjy01/preprocessing/calculator"
|
"starwiz.cn/sjy01/preprocessing/calculator"
|
||||||
)
|
)
|
||||||
@@ -129,7 +130,7 @@ type AuxPlatform struct {
|
|||||||
SS1_ExtenalImage bool // [407.(1)] 星敏1外部图像标志位 0x01:外部图像;0x00:关闭
|
SS1_ExtenalImage bool // [407.(1)] 星敏1外部图像标志位 0x01:外部图像;0x00:关闭
|
||||||
SS1_AttitudeActive bool // [407.(0)] 星敏1姿态有效标志位 0x01:激活;0x00:关闭
|
SS1_AttitudeActive bool // [407.(0)] 星敏1姿态有效标志位 0x01:激活;0x00:关闭
|
||||||
SS1_ImgFrmNo uint32 // [411-413] 星敏1图像帧号
|
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_YAV float64 // [419-420]
|
||||||
SS1_ZAV float64 // [421-422]
|
SS1_ZAV float64 // [421-422]
|
||||||
SS2_UTCTime uint32 // [424-427] 星敏2 UTC时间
|
SS2_UTCTime uint32 // [424-427] 星敏2 UTC时间
|
||||||
@@ -170,7 +171,7 @@ type AuxPlatform struct {
|
|||||||
CheckSum byte // [512] 校验和
|
CheckSum byte // [512] 校验和
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ap *AuxPlatform) Parse(data []byte) error {
|
func (ap *AuxPlatform) Decode(data []byte) error {
|
||||||
if len(data) < 512 {
|
if len(data) < 512 {
|
||||||
return ErrAuxPlatformDataLen
|
return ErrAuxPlatformDataLen
|
||||||
}
|
}
|
||||||
@@ -337,19 +338,23 @@ func (ap AuxPlatform) Print() {
|
|||||||
pp.Println(ap)
|
pp.Println(ap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ap AuxPlatform) SaveXlsx(row *xlsx.Row) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Extractor 辅助数据提取器
|
// Extractor 辅助数据提取器
|
||||||
// auxfile 辅助数据文件路径
|
// auxfile 辅助数据文件路径
|
||||||
func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
||||||
data, err := os.ReadFile(auxfile)
|
data, err := os.ReadFile(auxfile)
|
||||||
if err != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var aps []*AuxPlatform
|
var aps []*AuxPlatform
|
||||||
for i := 0; i < len(data); i += 24 + 128 + 512 {
|
for i := 0; i < len(data); i += 24 + 128 + 512 {
|
||||||
ap := AuxPlatform{}
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +392,7 @@ func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
|||||||
func (e *Extractor) ParseAuxPlatformWithHead(auxfile string) ([]*AuxPlatform, error) {
|
func (e *Extractor) ParseAuxPlatformWithHead(auxfile string) ([]*AuxPlatform, error) {
|
||||||
data, err := os.ReadFile(auxfile)
|
data, err := os.ReadFile(auxfile)
|
||||||
if err != nil {
|
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
|
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"
|
"bytes"
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BSQWriter struct {
|
|
||||||
filepath string
|
|
||||||
fio *os.File
|
|
||||||
w io.Writer
|
|
||||||
content *EnviHdr
|
|
||||||
}
|
|
||||||
|
|
||||||
var HDRTemplate = `ENVI
|
var HDRTemplate = `ENVI
|
||||||
description = {
|
description = {
|
||||||
File Imported into ENVI.}
|
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
|
toolchain go1.21.0
|
||||||
|
|
||||||
require github.com/twpayne/go-proj/v10 v10.2.0
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/onsi/gomega v1.33.1 // 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/crypto v0.23.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/term v0.20.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/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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.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 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
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/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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
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/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 h1:h33hNTZ9nVFNP3u2Fsgz8JXiF5JINoZfFq4SvKJwNcs=
|
||||||
github.com/k0kubun/pp/v3 v3.2.0/go.mod h1:ODtJQbQcIRfAD3N+theGCV1m/CBxweERz2dapdz1EwA=
|
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 h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
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=
|
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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
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/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
|
||||||
github.com/twpayne/go-proj/v10 v10.2.0/go.mod h1:BU5zbXY6XmKenoyf+DbIg7joKlKTJM2rEssPMPJZYjY=
|
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 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
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=
|
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.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
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 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/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 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
|||||||
Reference in New Issue
Block a user