get raw data
This commit is contained in:
10
aux/attitude.go
Normal file
10
aux/attitude.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package aux
|
||||||
|
|
||||||
|
/*
|
||||||
|
将欧拉角 (yaw, pitch, roll) 转换为旋转矩阵
|
||||||
|
|
||||||
|
参数:
|
||||||
|
- yaw: 偏航角(绕Z轴旋转)
|
||||||
|
- pitch: 俯仰角(绕Y轴旋转)
|
||||||
|
- roll: 滚转角(绕X轴旋转)
|
||||||
|
*/
|
||||||
114
aux/aux.go
Normal file
114
aux/aux.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package aux
|
||||||
|
|
||||||
|
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 := 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)
|
||||||
|
}
|
||||||
1
aux/orbit.go
Normal file
1
aux/orbit.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package aux
|
||||||
@@ -17,16 +17,17 @@ var extractCmd = &cobra.Command{
|
|||||||
Long: `Extract data from raw data files`,
|
Long: `Extract data from raw data files`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
params := extract.Params{
|
params := extract.Params{
|
||||||
InputData: fmt.Sprintf("demo/%s.dat", dataId),
|
InputData: fmt.Sprintf("demo/data/%s.dat", dataId),
|
||||||
OutputPath: "demo/output",
|
OutputPath: "demo/output",
|
||||||
TempPath: "demo/temp",
|
TempPath: "demo/temp",
|
||||||
DataId: dataId,
|
DataId: dataId,
|
||||||
|
Satellite: "SJY01",
|
||||||
}
|
}
|
||||||
p := extract.NewExtractor(¶ms)
|
p := extract.NewExtractor(¶ms)
|
||||||
p.ExtractAosData()
|
aos, _ := p.ExtractAosData()
|
||||||
dats, _ := p.ExtractOriginalImageData()
|
dats, _ := p.ExtractOriginalImageData(aos)
|
||||||
for _, d := range dats {
|
for i, d := range dats {
|
||||||
p.SeprateAuxAndImgData(d)
|
p.SeprateAuxAndImgData(d, i)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -34,5 +35,5 @@ var extractCmd = &cobra.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(extractCmd)
|
rootCmd.AddCommand(extractCmd)
|
||||||
|
|
||||||
extractCmd.Flags().StringVarP(&dataId, "data id", "d", "051513", "051513")
|
extractCmd.Flags().StringVarP(&dataId, "data-id", "d", "051513", "051513")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,16 @@ var parseCmd = &cobra.Command{
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
params := extract.Params{
|
params := extract.Params{
|
||||||
InputData: "demo/051513.dat",
|
InputData: "demo/data/051513.dat",
|
||||||
OutputPath: "demo/output",
|
OutputPath: "demo/output",
|
||||||
TempPath: "demo/temp",
|
TempPath: "demo/temp",
|
||||||
DataId: "051513",
|
DataId: "051513",
|
||||||
|
Satellite: "SJY01",
|
||||||
}
|
}
|
||||||
p := extract.NewExtractor(¶ms)
|
p := extract.NewExtractor(¶ms)
|
||||||
// p.ParseAuxPlatform("demo/output/051513_S46_AUX1.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())
|
||||||
p.SeprateAuxAndImgData("demo/temp/051513_S46.dat")
|
// p.SeprateAuxAndImgData("demo/temp/051513_S46.dat", 1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ var AOSSyncWord = []byte{0x1A, 0xCF, 0xFC, 0x1D}
|
|||||||
type AOSFrame struct {
|
type AOSFrame struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Extractor) ExtractAosData() error {
|
func (p *Extractor) ExtractAosData() (string, error) {
|
||||||
// 打开传输帧文件 - 一次读入内存
|
// 打开传输帧文件 - 一次读入内存
|
||||||
rawData, err := os.ReadFile(p.params.InputData)
|
rawData, err := os.ReadFile(p.params.InputData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("read data from", p.params.InputData, "error:", err.Error())
|
log.Println("read data from", p.params.InputData, "error:", err.Error())
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
name := filepath.Base(p.params.InputData)
|
name := filepath.Base(p.params.InputData)
|
||||||
@@ -33,7 +33,7 @@ func (p *Extractor) ExtractAosData() error {
|
|||||||
os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("create data err", err.Error())
|
fmt.Println("create data err", err.Error())
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
defer foData.Close()
|
defer foData.Close()
|
||||||
wData := bufio.NewWriter(foData)
|
wData := bufio.NewWriter(foData)
|
||||||
@@ -74,7 +74,7 @@ func (p *Extractor) ExtractAosData() error {
|
|||||||
log.Println("valid AOS frame cnt:", validFrameCnt)
|
log.Println("valid AOS frame cnt:", validFrameCnt)
|
||||||
log.Println("error AOS frame cnt:", errFrameCnt)
|
log.Println("error AOS frame cnt:", errFrameCnt)
|
||||||
|
|
||||||
return nil
|
return aosDataFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LDPCCheck(frame []byte) error {
|
func LDPCCheck(frame []byte) error {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -62,7 +63,7 @@ func (afh *AuxFrameHead) Decode(data []byte) error {
|
|||||||
afh.IsLinerMatrix = (afh.ImgMode&(1<<5) == 0x0 && afh.ImgMode&(1<<6) == 0x0 && afh.ImgMode&(1<<7) == 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.SerialNo = binary.BigEndian.Uint32(data[12:16])
|
||||||
afh.TimeSec = binary.BigEndian.Uint32(data[16:20])
|
afh.TimeSec = binary.BigEndian.Uint32(data[16:20])
|
||||||
afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22])) //binary.BigEndian.Uint32(data[20:23])
|
afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22]))
|
||||||
afh.FileNo = data[23]
|
afh.FileNo = data[23]
|
||||||
|
|
||||||
afh.RowLength = afh.LengthOfRow()
|
afh.RowLength = afh.LengthOfRow()
|
||||||
@@ -112,7 +113,7 @@ type Record struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
|
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
|
||||||
func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
func (p *Extractor) SeprateAuxAndImgData(sDataFile string, segmentIndex int) error {
|
||||||
// 打开传输帧文件 - 一次读入内存
|
// 打开传输帧文件 - 一次读入内存
|
||||||
sData, err := os.ReadFile(sDataFile)
|
sData, err := os.ReadFile(sDataFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -127,6 +128,8 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
defer fimg.Close()
|
defer fimg.Close()
|
||||||
fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n")
|
fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n")
|
||||||
var qmap []*Record
|
var qmap []*Record
|
||||||
|
var startAuxLine bool
|
||||||
|
var preSN uint32
|
||||||
for i := 0; i < len(sData); {
|
for i := 0; i < len(sData); {
|
||||||
// 解析帧
|
// 解析帧
|
||||||
if i+24 > len(sData) {
|
if i+24 > len(sData) {
|
||||||
@@ -148,22 +151,22 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
if !afh.IsValidFrmHead {
|
if !afh.IsValidFrmHead {
|
||||||
log.Debugf("[%d] invalid frame head of original raw data %v", i, afh.FrmHead)
|
log.Debugf("[%d] invalid frame head of original raw data %v", i, afh.FrmHead)
|
||||||
i += 1
|
i += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &Record{index: i, frmHead: afh}
|
||||||
|
qmap = append(qmap, r)
|
||||||
|
|
||||||
|
utcTime := binary.BigEndian.Uint32(sData[i+32 : i+36])
|
||||||
|
|
||||||
|
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), int64(afh.TimeSecFrac)*1000)
|
||||||
|
tAux := time.Unix(int64(utcTime+uint32(ReferenceTime2000)), 0)
|
||||||
|
|
||||||
|
startAuxLine = tAux.Year() == t.Year() && tAux.Month() == t.Month() && tAux.Day() == t.Day() &&
|
||||||
|
tAux.Hour() == t.Hour() && tAux.Minute() == t.Minute()
|
||||||
|
if !startAuxLine {
|
||||||
|
// fimg.WriteString(fmt.Sprintf("-----%d not AUX Start -----\n", afh.SerialNo))
|
||||||
} else {
|
} else {
|
||||||
r := &Record{index: i, frmHead: afh}
|
|
||||||
qmap = append(qmap, r)
|
|
||||||
i += 24
|
|
||||||
|
|
||||||
utcTime := binary.BigEndian.Uint32(sData[i+32 : i+36])
|
|
||||||
|
|
||||||
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), 0)
|
|
||||||
tAux := time.Unix(int64(utcTime), 0)
|
|
||||||
startAuxLine := tAux.Year() == t.Year() && tAux.Month() == t.Month() && tAux.Day() == t.Day() &&
|
|
||||||
tAux.Hour() == t.Hour() && tAux.Minute() == t.Minute()
|
|
||||||
|
|
||||||
if startAuxLine {
|
|
||||||
fimg.WriteString("----- AUX Start -----\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n",
|
fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n",
|
||||||
i,
|
i,
|
||||||
afh.SerialNo,
|
afh.SerialNo,
|
||||||
@@ -171,7 +174,14 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
t.String(),
|
t.String(),
|
||||||
tAux.String(),
|
tAux.String(),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if afh.SerialNo-preSN != 16 {
|
||||||
|
fmt.Println("serial number not continuous", afh.SerialNo, preSN)
|
||||||
|
}
|
||||||
|
preSN = afh.SerialNo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i += afh.RowLength
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(qmap, func(i, j int) bool {
|
sort.Slice(qmap, func(i, j int) bool {
|
||||||
@@ -196,31 +206,34 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
defer waux1.Flush()
|
defer waux1.Flush()
|
||||||
defer faux1.Close()
|
defer faux1.Close()
|
||||||
|
|
||||||
pan := outputDir + "/" + name + "_IMG_PAN.RAW"
|
pan := outputDir + "/" + name + "_PAN.RAW"
|
||||||
os.Remove(pan)
|
os.Remove(pan)
|
||||||
fpan, _ := os.OpenFile(pan, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
fpan, _ := os.OpenFile(pan, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||||
wpan := bufio.NewWriter(fpan)
|
wpan := bufio.NewWriter(fpan)
|
||||||
defer wpan.Flush()
|
defer wpan.Flush()
|
||||||
defer fpan.Close()
|
defer fpan.Close()
|
||||||
panEnviHdr := EnviHdr{}
|
panEnviHdr := EnviHdr{}
|
||||||
wpanHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_PAN.HDR", &panEnviHdr)
|
wpanHdr, _ := NewBSQWriter(outputDir+"/"+name+"_PAN.HDR", &panEnviHdr)
|
||||||
defer wpanHdr.Close()
|
defer wpanHdr.Close()
|
||||||
|
|
||||||
// 先按单波段存储,再按波段组合存储为 BSQ 格式的 MSS
|
// 先按单波段存储,再按波段组合存储为 BSQ 格式的 MSS
|
||||||
mss := outputDir + "/" + name + "_IMG_MSS.RAW"
|
mss := outputDir + "/" + name + "_MSS.RAW"
|
||||||
os.Remove(mss)
|
os.Remove(mss)
|
||||||
fmss, _ := os.OpenFile(mss, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
fmss, _ := os.OpenFile(mss, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||||
wmss := bufio.NewWriter(fmss)
|
wmss := bufio.NewWriter(fmss)
|
||||||
defer wmss.Flush()
|
defer wmss.Flush()
|
||||||
defer fmss.Close()
|
defer fmss.Close()
|
||||||
mssEnviHdr := EnviHdr{}
|
mssEnviHdr := EnviHdr{}
|
||||||
wmssHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_MSS.HDR", &mssEnviHdr)
|
wmssHdr, _ := NewBSQWriter(outputDir+"/"+name+"_MSS.HDR", &mssEnviHdr)
|
||||||
defer wmssHdr.Close()
|
defer wmssHdr.Close()
|
||||||
|
|
||||||
var afh AuxFrameHead
|
var afh AuxFrameHead
|
||||||
dataLen := len(sData)
|
dataLen := len(sData)
|
||||||
|
|
||||||
mssData := make([][]byte, 4)
|
mssData := make([][]byte, 4)
|
||||||
|
var firstLineFound bool
|
||||||
|
var totalLines int
|
||||||
|
var pancount int
|
||||||
for i := 0; i < dataLen; {
|
for i := 0; i < dataLen; {
|
||||||
if i+4 > dataLen {
|
if i+4 > dataLen {
|
||||||
logrus.Println("end of data, dataLen:", dataLen, "i:", i)
|
logrus.Println("end of data, dataLen:", dataLen, "i:", i)
|
||||||
@@ -262,6 +275,21 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通过中心辅助时间判断是否第一行数据
|
||||||
|
if !firstLineFound {
|
||||||
|
utcTime := binary.BigEndian.Uint32(sData[i+32 : i+36])
|
||||||
|
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), int64(afh.TimeSecFrac)*1000)
|
||||||
|
tAux := time.Unix(int64(utcTime+uint32(ReferenceTime2000)), 0)
|
||||||
|
firstLineFound = tAux.Year() == t.Year() && tAux.Month() == t.Month() && tAux.Day() == t.Day() &&
|
||||||
|
tAux.Hour() == t.Hour() && tAux.Minute() == t.Minute()
|
||||||
|
if !firstLineFound {
|
||||||
|
log.Info("did not find first line of aux data, skip this frame: ", afh.SerialNo)
|
||||||
|
i += afh.RowLength
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalLines += 1
|
||||||
|
|
||||||
// 存储辅助数据到临时文件
|
// 存储辅助数据到临时文件
|
||||||
dataIndex := i + 24
|
dataIndex := i + 24
|
||||||
waux0.Write(sData[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据
|
waux0.Write(sData[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据
|
||||||
@@ -271,29 +299,31 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
|
|
||||||
// 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件
|
// 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件
|
||||||
if afh.B0 {
|
if afh.B0 {
|
||||||
wpan.Write(sData[dataIndex : dataIndex+19040])
|
// wpan.Write(sData[dataIndex : dataIndex+19040])
|
||||||
|
write16bPixelLittleEndian(wpan, sData[dataIndex:dataIndex+19040])
|
||||||
dataIndex += 19040
|
dataIndex += 19040
|
||||||
panEnviHdr.Lines += 1
|
panEnviHdr.Lines += 1
|
||||||
|
pancount += 19040
|
||||||
}
|
}
|
||||||
|
|
||||||
if afh.B1 {
|
if afh.B1 {
|
||||||
// wmss.Write(sData[dataIndex : dataIndex+1192])
|
// write16bPixelLittleEndian(wmss, sData[dataIndex:dataIndex+1192])
|
||||||
mssData[0] = append(mssData[0], sData[dataIndex:dataIndex+1192]...)
|
mssData[0] = append(mssData[0], sData[dataIndex:dataIndex+1192]...)
|
||||||
dataIndex += 1192
|
dataIndex += 1192
|
||||||
mssEnviHdr.Lines += 1
|
mssEnviHdr.Lines += 1
|
||||||
}
|
}
|
||||||
if afh.B2 {
|
if afh.B2 {
|
||||||
// wmss.Write(sData[dataIndex : dataIndex+1192])
|
// write16bPixelLittleEndian(wmss, sData[dataIndex:dataIndex+1192])
|
||||||
mssData[1] = append(mssData[1], sData[dataIndex:dataIndex+1192]...)
|
mssData[1] = append(mssData[1], sData[dataIndex:dataIndex+1192]...)
|
||||||
dataIndex += 1192
|
dataIndex += 1192
|
||||||
}
|
}
|
||||||
if afh.B3 {
|
if afh.B3 {
|
||||||
// wmss.Write(sData[dataIndex : dataIndex+1192])
|
// write16bPixelLittleEndian(wmss, sData[dataIndex:dataIndex+1192])
|
||||||
mssData[2] = append(mssData[2], sData[dataIndex:dataIndex+1192]...)
|
mssData[2] = append(mssData[2], sData[dataIndex:dataIndex+1192]...)
|
||||||
dataIndex += 1192
|
dataIndex += 1192
|
||||||
}
|
}
|
||||||
if afh.B4 {
|
if afh.B4 {
|
||||||
// wmss.Write(sData[dataIndex : dataIndex+1192])
|
// write16bPixelLittleEndian(wmss, sData[dataIndex:dataIndex+1192])
|
||||||
mssData[3] = append(mssData[3], sData[dataIndex:dataIndex+1192]...)
|
mssData[3] = append(mssData[3], sData[dataIndex:dataIndex+1192]...)
|
||||||
dataIndex += 1192
|
dataIndex += 1192
|
||||||
}
|
}
|
||||||
@@ -304,7 +334,7 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
if len(mssData[i]) > 0 {
|
if len(mssData[i]) > 0 {
|
||||||
log.Println("write mss data of band B", i+1)
|
log.Println("write mss data of band B", i+1)
|
||||||
_, err := wmss.Write(mssData[i])
|
// _, err := write16bPixelLittleEndian(wmss, mssData[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("write mss data error:", err.Error())
|
log.Error("write mss data error:", err.Error())
|
||||||
}
|
}
|
||||||
@@ -312,14 +342,24 @@ func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write16bPixelLittleEndian(wmss, mssData[2])
|
||||||
|
|
||||||
panEnviHdr.Samples = 9520
|
panEnviHdr.Samples = 9520
|
||||||
panEnviHdr.Bands = 1
|
panEnviHdr.Bands = 1
|
||||||
wpanHdr.Write([]byte(panEnviHdr.String()))
|
wpanHdr.Write([]byte(panEnviHdr.String()))
|
||||||
|
|
||||||
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
|
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
|
||||||
mssEnviHdr.Samples = 2384
|
mssEnviHdr.Samples = 2384
|
||||||
mssEnviHdr.Bands = bands
|
mssEnviHdr.Bands = 1
|
||||||
wmssHdr.Write([]byte(mssEnviHdr.String()))
|
wmssHdr.Write([]byte(mssEnviHdr.String()))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入 16 位像素值,小端序
|
||||||
|
func write16bPixelLittleEndian(w io.Writer, data []byte) (int, error) {
|
||||||
|
for i := 0; i < len(data)-1; i += 2 {
|
||||||
|
data[i], data[i+1] = data[i+1], data[i]
|
||||||
|
}
|
||||||
|
return w.Write(data)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package extract
|
package extract
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
// 卫星时间起点 北京时间 2000-01-01 20:00:00
|
// 卫星时间起点 北京时间 2000-01-01 20:00:00
|
||||||
var (
|
var (
|
||||||
ReferenceTime2000 = 946728000
|
ReferenceTime2000 = 946728000
|
||||||
@@ -7,4 +9,86 @@ var (
|
|||||||
|
|
||||||
// 焦面电箱辅助数据 128 字节 (每 16 行原始图像数据为一组)
|
// 焦面电箱辅助数据 128 字节 (每 16 行原始图像数据为一组)
|
||||||
type AuxFocalBox struct {
|
type AuxFocalBox struct {
|
||||||
|
TransferTime float32 // 执行转移时间 0.5us/bit
|
||||||
|
TrainingDone byte // 1B成功;0B失败
|
||||||
|
WorkMode byte // 工作模式 0B正常;1B故障
|
||||||
|
IntegralDirection byte // 积分方向 1B正向;0B反向
|
||||||
|
PGAGain byte // PGA增益
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ab *AuxFocalBox) Decode(data []byte) error {
|
||||||
|
byte0 := data[0] & 0b00111111
|
||||||
|
ab.TransferTime = float32(uint32(byte0)<<16|uint32(data[1])<<8|uint32(data[2])) * 0.5
|
||||||
|
ab.TrainingDone = data[3] & 0b10000000
|
||||||
|
ab.WorkMode = data[3] & 0b01000000
|
||||||
|
ab.IntegralDirection = data[3] & 0b00100000
|
||||||
|
ab.PGAGain = data[3] & 0b00011111
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ab AuxFocalBox) String() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
`执行转移时间:%f us\n
|
||||||
|
TrainingDone:%x\n
|
||||||
|
工作模式:%x\n
|
||||||
|
积分方向:%x\n
|
||||||
|
PGA增益:%s
|
||||||
|
`,
|
||||||
|
ab.TransferTime,
|
||||||
|
ab.TrainingDone,
|
||||||
|
ab.WorkMode,
|
||||||
|
ab.IntegralDirection,
|
||||||
|
ab.PGAGainValue(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ab AuxFocalBox) PGAGainValue() string {
|
||||||
|
switch ab.PGAGain {
|
||||||
|
case 0b0000:
|
||||||
|
return "0.75x"
|
||||||
|
case 0b0001:
|
||||||
|
return "1.25x"
|
||||||
|
case 0b0010:
|
||||||
|
return "1.75x"
|
||||||
|
case 0b0011:
|
||||||
|
return "2.25x"
|
||||||
|
case 0b0100:
|
||||||
|
return "2.75x"
|
||||||
|
case 0b0101:
|
||||||
|
return "3.25x"
|
||||||
|
case 0b0110:
|
||||||
|
return "3.75x"
|
||||||
|
case 0b0111:
|
||||||
|
return "4.25x"
|
||||||
|
case 0b1000:
|
||||||
|
return "4.75x"
|
||||||
|
case 0b1001:
|
||||||
|
return "5.25x"
|
||||||
|
case 0b1010:
|
||||||
|
return "5.75x"
|
||||||
|
case 0b10000:
|
||||||
|
return "1x"
|
||||||
|
case 0b10001:
|
||||||
|
return "1.5x"
|
||||||
|
case 0b10010:
|
||||||
|
return "2x"
|
||||||
|
case 0b10011:
|
||||||
|
return "2.5x"
|
||||||
|
case 0b10100:
|
||||||
|
return "3x"
|
||||||
|
case 0b10101:
|
||||||
|
return "3.5x"
|
||||||
|
case 0b10110:
|
||||||
|
return "4x"
|
||||||
|
case 0b10111:
|
||||||
|
return "4.5x"
|
||||||
|
case 0b11000:
|
||||||
|
return "5x"
|
||||||
|
case 0b11001:
|
||||||
|
return "5.5x"
|
||||||
|
case 0b11010:
|
||||||
|
return "6x"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AuxPlatformFrmSize = 512 // 512 bytes
|
const AuxPlatformFrmSize = 512 // 512 bytes
|
||||||
@@ -90,7 +91,8 @@ type AuxPlatform struct {
|
|||||||
Reserved1 [4]byte // 预留字节
|
Reserved1 [4]byte // 预留字节
|
||||||
Reserved2 [2]byte // 预留字节
|
Reserved2 [2]byte // 预留字节
|
||||||
Reserved3 [2]byte // 预留字节
|
Reserved3 [2]byte // 预留字节
|
||||||
// 241 - 311 暂不解析
|
// 241.0 - 311.0 波道1参数
|
||||||
|
// 241.1 - 311.1 波道2参数
|
||||||
WGS84PosX float64 // [312-315]计算当前WGS 84位置X 单位:0.01米
|
WGS84PosX float64 // [312-315]计算当前WGS 84位置X 单位:0.01米
|
||||||
WGS84PosY float64 // [316-319]
|
WGS84PosY float64 // [316-319]
|
||||||
WGS84PosZ float64 // [320-323]
|
WGS84PosZ float64 // [320-323]
|
||||||
@@ -191,6 +193,70 @@ func (e *Extractor) ParseAuxPlatform(auxfile string) ([]*AuxPlatform, error) {
|
|||||||
return aps, nil
|
return aps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fimg, _ := os.Create("demo/temp/ref_051622_aux_img.txt")
|
||||||
|
defer fimg.Close()
|
||||||
|
fimg.WriteString("index 流水号 文件号 时间秒 秒小数 utcTime\n")
|
||||||
|
|
||||||
|
var aps []*AuxPlatform
|
||||||
|
rows := 0
|
||||||
|
for i := 0; i < len(data); {
|
||||||
|
if data[i] == 0xD1 && data[i+1] == 0x5B && data[i+2] == 0xD1 && data[i+3] == 0x5B {
|
||||||
|
log.Debug("find package head: 0xD15BD15B")
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
// log.Println(i,"not find package head: 0xD15BD15B, skip 1 byte")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
afh := &AuxFrameHead{}
|
||||||
|
afh.Decode(data[i : i+24])
|
||||||
|
|
||||||
|
if !afh.IsValidFrmHead {
|
||||||
|
log.Debugf("[%d] invalid frame head of original raw data %v", i, afh.FrmHead)
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (afh.SerialNo-1)%16 == 0 {
|
||||||
|
|
||||||
|
ab := &AuxFocalBox{}
|
||||||
|
ab.Decode(data[i+24 : i+32])
|
||||||
|
fmt.Println(ab.String())
|
||||||
|
|
||||||
|
utcTime := binary.BigEndian.Uint32(data[i+32 : i+36])
|
||||||
|
|
||||||
|
// t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), int64(afh.TimeSecFrac)*1000)
|
||||||
|
taux := time.Unix(int64(utcTime+uint32(ReferenceTime2000)), 0)
|
||||||
|
|
||||||
|
fimg.WriteString(
|
||||||
|
fmt.Sprintf("%d %d %d %d %d %d %s\n",
|
||||||
|
i,
|
||||||
|
afh.SerialNo,
|
||||||
|
afh.FileNo,
|
||||||
|
afh.TimeSec,
|
||||||
|
afh.TimeSecFrac,
|
||||||
|
utcTime,
|
||||||
|
taux.String(),
|
||||||
|
))
|
||||||
|
|
||||||
|
rows++
|
||||||
|
// if rows > 32 {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 64
|
||||||
|
|
||||||
|
}
|
||||||
|
return aps, nil
|
||||||
|
}
|
||||||
|
|
||||||
func Time2000UTCSec() int64 {
|
func Time2000UTCSec() int64 {
|
||||||
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2000-01-01 12:00:00", time.UTC)
|
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2000-01-01 12:00:00", time.UTC)
|
||||||
return t.Unix()
|
return t.Unix()
|
||||||
|
|||||||
@@ -46,10 +46,8 @@ func (t *TransFrame) Decode(frame []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 提取图像传输帧中的原始图像数据
|
// 提取图像传输帧中的原始图像数据
|
||||||
func (p *Extractor) ExtractOriginalImageData() ([]string, error) {
|
func (p *Extractor) ExtractOriginalImageData(aosDataFile string) ([]string, error) {
|
||||||
var sData []string
|
var sData []string
|
||||||
name := filepath.Base(p.params.InputData)
|
|
||||||
aosDataFile := filepath.Join(p.params.TempPath, AOSTempDataPrefix+name)
|
|
||||||
nullFrmCnt := 0
|
nullFrmCnt := 0
|
||||||
|
|
||||||
aosData, err := os.ReadFile(aosDataFile)
|
aosData, err := os.ReadFile(aosDataFile)
|
||||||
@@ -116,7 +114,10 @@ func (p *Extractor) ExtractOriginalImageData() ([]string, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s01 := filepath.Join(p.params.TempPath, fmt.Sprintf("%s_S%d.dat", p.params.DataId, k))
|
s01 := filepath.Join(p.params.TempPath, fmt.Sprintf("%s_%s_S%d.dat",
|
||||||
|
p.params.Satellite,
|
||||||
|
p.params.DataId,
|
||||||
|
k))
|
||||||
fo, err := os.OpenFile(s01,
|
fo, err := os.OpenFile(s01,
|
||||||
os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user