This commit is contained in:
nuknal
2024-08-22 16:32:27 +08:00
parent ca3e91b1d8
commit 6f2cfa797a
9 changed files with 300 additions and 305 deletions

View File

@@ -19,7 +19,6 @@ import (
"starwiz.cn/sjy01/image-proc/pkg/auxilary"
"starwiz.cn/sjy01/image-proc/pkg/calculator"
"starwiz.cn/sjy01/image-proc/pkg/config"
"starwiz.cn/sjy01/image-proc/pkg/payload"
)
func (r *Registrator) LoadAuxData() error {
@@ -30,10 +29,7 @@ func (r *Registrator) LoadAuxData() error {
gpsFile := strings.Replace(r.Params.AuxRawFile, ".AUX", ".gps.txt", 1)
r.AttQuaternion, _ = auxilary.StoreAtt(r.AuxPlatforms, attFile)
r.GPSs, _ = auxilary.StoreGPS(r.AuxPlatforms, gpsFile)
imgtime := auxilary.NewImageTime()
imgtime.Extract(r.AuxPlatforms)
imgtime.Print(100, 16)
r.ImageTime = auxilary.NewImageTime(r.AuxPlatforms)
return err
}
@@ -79,44 +75,14 @@ func (r *Registrator) SceneImageTime(scene *Scene) (start, center, end time.Time
return
}
// FIXME: This function is not accurate enough.
// FIXME: This function is not accurate enough. 四元数、成像时刻、GPS 等需要修改为插值获取
func (r *Registrator) SetSceneBoundary(scene *Scene) (topLeft, bottomRight orb.Point) {
startPosInAux, endPosInAux := r.SceneInAuxIndex(scene)
as := r.AuxPlatforms[startPosInAux]
ae := r.AuxPlatforms[endPosInAux]
startTime := time.Unix(int64(auxilary.ReferenceTime2000)+int64(as.UTCTimeSec), int64(as.Microsecond)*1000).UTC()
endTime := time.Unix(int64(auxilary.ReferenceTime2000)+int64(ae.UTCTimeSec), int64(ae.Microsecond)*1000).UTC()
startPos84 := []float64{as.W84PosX, as.W84PosY, as.W84PosZ}
endPos84 := []float64{ae.W84PosX, ae.W84PosY, ae.W84PosZ}
// FIXME: GPS 拟合效果不佳
// x0 := float64(r.auxHeads[startPosInAux].TimeSec) + float64(r.auxHeads[startPosInAux].TimeSecFrac)/10e6
// x1 := float64(r.auxHeads[endPosInAux].TimeSec) + float64(r.auxHeads[endPosInAux].TimeSecFrac)/10e6
// startPos84 = []float64{r.w84FitPre[0].Predict(x0), r.w84FitPre[1].Predict(x0), r.w84FitPre[2].Predict(x0)}
// endPos84 = []float64{r.w84FitPre[0].Predict(x1), r.w84FitPre[1].Predict(x1), r.w84FitPre[2].Predict(x1)}
// stepN := 2
// startPos84 = []float64{
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionX, x0, stepN),
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionY, x0, stepN),
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionZ, x0, stepN),
// }
// endPos84 = []float64{
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionX, x1, stepN),
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionY, x1, stepN),
// utils.InterpPolynomial(r.w84PositionTime, r.w84PositionZ, x1, stepN),
// }
// ------------------ 使用定姿态四元数计算图像边界 ------------------
log.Info("using attitude quaternion to calculate image boundary...")
Qsat2eci := calculator.Quaternion{W: as.QuatAttstarQ0, X: as.QuatAttstarQ1, Y: as.QuatAttstarQ2, Z: as.QuatAttstarQ3}
line0Start, _ := calculator.IntersectionAttitude(Qsat2eci, startPos84, startTime, 0)
line0End, _ := calculator.IntersectionAttitude(Qsat2eci, startPos84, startTime, payload.PAN_PIXEL_WIDTH)
Qsat2eci = calculator.Quaternion{W: ae.QuatAttstarQ0, X: ae.QuatAttstarQ1, Y: ae.QuatAttstarQ2, Z: ae.QuatAttstarQ3}
lineNStart, _ := calculator.IntersectionAttitude(Qsat2eci, endPos84, endTime, 0)
lineNEnd, _ := calculator.IntersectionAttitude(Qsat2eci, endPos84, endTime, payload.PAN_PIXEL_WIDTH)
line0Start := r.calculateLatLonH(scene, 0, 0, 0)
line0End := r.calculateLatLonH(scene, 0, scene.Width, 0)
lineNStart := r.calculateLatLonH(scene, scene.Height, 0, 0)
lineNEnd := r.calculateLatLonH(scene, scene.Height, scene.Width, 0)
// ------------------ 计算图像边界距离和分辨率 ------------------
W0 := geo.Distance(orb.Point{line0Start.Lon, line0Start.Lat}, orb.Point{line0End.Lon, line0End.Lat})
@@ -166,16 +132,16 @@ func (r *Registrator) SetSceneBoundary(scene *Scene) (topLeft, bottomRight orb.P
scene.Meta.Corners.LowerRight.Latitude = lineNEnd.Lat
scene.Meta.Corners.LowerRight.Longitude = lineNEnd.Lon
scene.Meta.SatPosX = startPos84[0]
scene.Meta.SatPosY = startPos84[1]
scene.Meta.SatPosZ = startPos84[2]
scene.Meta.Yaw = ae.Eular3 * 180 / math.Pi
scene.Meta.Pitch = ae.Eular2 * 180 / math.Pi
scene.Meta.Roll = ae.Eular1 * 180 / math.Pi
// scene.Meta.SatPosX = startPos84[0]
// scene.Meta.SatPosY = startPos84[1]
// scene.Meta.SatPosZ = startPos84[2]
// scene.Meta.Yaw = ae.Eular3 * 180 / math.Pi
// scene.Meta.Pitch = ae.Eular2 * 180 / math.Pi
// scene.Meta.Roll = ae.Eular1 * 180 / math.Pi
// 计算RPC
rpc := NewRPC(r, scene, strings.Replace(scene.Tiff, ".tiff", ".rpb", 1))
if err := rpc.SolveLeastSquares(); err != nil {
if err := rpc.RPC(); err != nil {
log.Error("calculate RPC failed: ", err)
} else {
rpc.SaveRpb()
@@ -207,3 +173,30 @@ func (r *Registrator) sceneOffsetInAuxIndex(scene *Scene, offset int) int {
}
return idx
}
// row, col 相对于图像景左上角, H 为地面目标点高度
func (r *Registrator) calculateLatLonH(scene *Scene, row, col, H int) calculator.IntersectionPoint {
// 内插值获取图像行时刻
ucam := col
cross := 16
if scene.Type == "MSS" {
cross = 4
ucam = 4 * col // 统一使用相机PAN像元宽度进行计算
}
imgrow := row + scene.Y
imgtime, _ := r.ImageTime.Interp(imgrow, cross)
nanosecond := (imgtime - math.Floor(imgtime)) * 1000000000
sattime := time.Unix(int64(imgtime), int64(nanosecond)).UTC()
// 球面线性插值得到姿态四元数
qECI := r.AttQuaternion.Slerp(imgtime)
// 拉格朗日插值得到卫星GPS坐标
p84 := r.GPSs.Lagrange(imgtime)
// 计算目标点在WGS84坐标系下的坐标
cECI := calculator.Quaternion{W: qECI.Q0, X: qECI.Q1, Y: qECI.Q2, Z: qECI.Q3}
groudPoint84, _ := calculator.Camera2GroundPoint(cECI,
[]float64{p84.X84, p84.Y84, p84.Z84},
sattime, ucam, H)
return groudPoint84
}