rpc 非线性方法
This commit is contained in:
1
go.mod
1
go.mod
@@ -63,6 +63,7 @@ require (
|
|||||||
golang.org/x/oauth2 v0.16.0 // indirect
|
golang.org/x/oauth2 v0.16.0 // indirect
|
||||||
golang.org/x/term v0.20.0 // indirect
|
golang.org/x/term v0.20.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/text v0.15.0 // indirect
|
||||||
|
golang.org/x/tools v0.20.0 // indirect
|
||||||
google.golang.org/api v0.155.0 // indirect
|
google.golang.org/api v0.155.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -1716,6 +1716,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
|||||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||||
|
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||||
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ func CameraDirectionVec(u, v float64) []float64 {
|
|||||||
directionVec[1] = (v - PANPixels/2) * PANCellSize / 1000.0 / 1000.0 // y方向, mm
|
directionVec[1] = (v - PANPixels/2) * PANCellSize / 1000.0 / 1000.0 // y方向, mm
|
||||||
directionVec[2] = -FocalLength / 1000.0 // z方向, mm
|
directionVec[2] = -FocalLength / 1000.0 // z方向, mm
|
||||||
|
|
||||||
|
// deltaFOV := (FOV * math.Pi / 180) / PANPixels
|
||||||
|
// directionVec[1] = math.Tan((v - PANPixels/2) * deltaFOV)
|
||||||
|
// directionVec[2] = -1
|
||||||
|
|
||||||
// 归一化
|
// 归一化
|
||||||
// fmt.Printf("Direction Vector: (%.6f, %.6f, %.6f) \n", directionVec[0], directionVec[1], directionVec[2])
|
// fmt.Printf("Direction Vector: (%.6f, %.6f, %.6f) \n", directionVec[0], directionVec[1], directionVec[2])
|
||||||
// directionVec = normalizeVec(directionVec)
|
// directionVec = normalizeVec(directionVec)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func gridImage2(m, n, height, width, k, hmin, hmax int) []*GridPoint {
|
|||||||
hmin = hmin - 500
|
hmin = hmin - 500
|
||||||
dh := (hmax - hmin) / (k)
|
dh := (hmax - hmin) / (k)
|
||||||
var h []int
|
var h []int
|
||||||
for i := 0; i <= k; i++ {
|
for i := 1; i <= k; i++ {
|
||||||
h = append(h, hmin+dh*i)
|
h = append(h, hmin+dh*i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ type RPCModel struct {
|
|||||||
// rational polynomial coeffients
|
// rational polynomial coeffients
|
||||||
func NewRPC(r *Registrator, scene *Scene, rpb string) *RPC {
|
func NewRPC(r *Registrator, scene *Scene, rpb string) *RPC {
|
||||||
rpc := RPC{
|
rpc := RPC{
|
||||||
elevationLayer: 5,
|
elevationLayer: 4,
|
||||||
gridsize: 5,
|
gridsize: 19,
|
||||||
registrator: r,
|
registrator: r,
|
||||||
scene: scene,
|
scene: scene,
|
||||||
rpb: rpb,
|
rpb: rpb,
|
||||||
|
|||||||
@@ -3,11 +3,19 @@ package producer
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"sort"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gonum.org/v1/gonum/mat"
|
"gonum.org/v1/gonum/mat"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type VX struct {
|
||||||
|
v float64
|
||||||
|
x mat.VecDense
|
||||||
|
}
|
||||||
|
|
||||||
|
const epsilon = 1e-4
|
||||||
|
|
||||||
func normalize(v *mat.VecDense) (*mat.VecDense, float64, float64) {
|
func normalize(v *mat.VecDense) (*mat.VecDense, float64, float64) {
|
||||||
var vOff, vScale float64
|
var vOff, vScale float64
|
||||||
vOff = mat.Sum(v) / float64(v.Len())
|
vOff = mat.Sum(v) / float64(v.Len())
|
||||||
@@ -34,102 +42,102 @@ func solveCoefficients(f, latVec, lonVec, heightVec *mat.VecDense) ([]float64, e
|
|||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
weights.SetDiag(i, 1.0)
|
weights.SetDiag(i, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算初始值
|
||||||
|
var x0 mat.VecDense
|
||||||
w2 := mat.NewDiagDense(n, nil)
|
w2 := mat.NewDiagDense(n, nil)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
w2.SetDiag(i, weights.At(i, i)*weights.At(i, i))
|
||||||
|
}
|
||||||
|
var MtW2 mat.Dense
|
||||||
|
MtW2.Mul(M.T(), w2)
|
||||||
|
var MtW2M mat.Dense
|
||||||
|
MtW2M.Mul(&MtW2, M)
|
||||||
|
invMtW2M, err := invertRPCMatrix(&MtW2M)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var MtW2F mat.VecDense
|
||||||
|
MtW2F.MulVec(&MtW2, f)
|
||||||
|
x0.MulVec(invMtW2M, &MtW2F)
|
||||||
|
|
||||||
|
numerator := mat.NewVecDense(20, nil)
|
||||||
|
denominator := mat.NewVecDense(20, nil)
|
||||||
|
denominator.SetVec(0, 1.0)
|
||||||
|
numerator.SetVec(0, x0.AtVec(0))
|
||||||
|
for i := 1; i < 20; i++ {
|
||||||
|
numerator.SetVec(i, x0.AtVec(i))
|
||||||
|
denominator.SetVec(i, x0.AtVec(i+19))
|
||||||
|
}
|
||||||
|
|
||||||
|
num, den, err := solveNelderMead(numerator, denominator, f, latVec, lonVec, heightVec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var coeffs []float64
|
||||||
|
coeffs = append(coeffs, num.RawVector().Data...)
|
||||||
|
for i := 1; i < 20; i++ {
|
||||||
|
coeffs = append(coeffs, den.AtVec(i))
|
||||||
|
}
|
||||||
|
return coeffs, nil
|
||||||
|
|
||||||
|
// 迭代
|
||||||
|
var wm mat.Dense
|
||||||
|
var wmx, wf mat.VecDense
|
||||||
|
var x1 mat.VecDense
|
||||||
|
|
||||||
|
var vx []*VX
|
||||||
|
v0 := 0.0
|
||||||
iterations := 0
|
iterations := 0
|
||||||
var x mat.VecDense
|
maxIterations := 10
|
||||||
// var e0 float64
|
|
||||||
|
|
||||||
for iterations < 20 {
|
for iterations < maxIterations {
|
||||||
iterations++
|
denominator.SetVec(0, 1.0)
|
||||||
|
for idx := 1; idx < 20; idx++ {
|
||||||
// w2 = weights^2
|
denominator.SetVec(idx, x0.AtVec(idx+19))
|
||||||
|
}
|
||||||
|
weights = setupWeightMatrix(denominator, latVec, lonVec, heightVec)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
w2.SetDiag(i, weights.At(i, i)*weights.At(i, i))
|
w2.SetDiag(i, weights.At(i, i)*weights.At(i, i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x = (M^T * w2 * M)^-1 * M^T * w2 * R
|
|
||||||
var MtW2 mat.Dense
|
|
||||||
MtW2.Mul(M.T(), w2)
|
MtW2.Mul(M.T(), w2)
|
||||||
var MtW2M mat.Dense
|
|
||||||
MtW2M.Mul(&MtW2, M)
|
MtW2M.Mul(&MtW2, M)
|
||||||
|
|
||||||
invMtW2M, err := invertRPCMatrix(&MtW2M)
|
invMtW2M, err := invertRPCMatrix(&MtW2M)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var MtW2F mat.VecDense
|
|
||||||
MtW2F.MulVec(&MtW2, f)
|
MtW2F.MulVec(&MtW2, f)
|
||||||
|
x1.MulVec(invMtW2M, &MtW2F)
|
||||||
|
|
||||||
x.MulVec(invMtW2M, &MtW2F)
|
wm.Mul(weights, M)
|
||||||
|
wmx.MulVec(&wm, &x1)
|
||||||
|
wf.MulVec(weights, f)
|
||||||
|
wmx.SubVec(&wmx, &wf)
|
||||||
|
wmx.MulElemVec(&wmx, &wmx)
|
||||||
|
v := math.Sqrt(mat.Max(&wmx))
|
||||||
|
log.Println("iteration:", iterations, "v-err:", v)
|
||||||
|
|
||||||
numerator := mat.NewVecDense(20, nil)
|
vx = append(vx, &VX{v: v, x: x1})
|
||||||
denominator := mat.NewVecDense(20, nil)
|
if math.Abs(v-v0) < epsilon {
|
||||||
numerator.SetVec(0, x.AtVec(0))
|
|
||||||
denominator.SetVec(0, 1.0)
|
|
||||||
for idx := 1; idx < 20; idx++ {
|
|
||||||
numerator.SetVec(idx, x.AtVec(idx))
|
|
||||||
denominator.SetVec(idx, x.AtVec(idx+19))
|
|
||||||
}
|
|
||||||
|
|
||||||
weights = setupWeightMatrix(denominator, latVec, lonVec, heightVec)
|
|
||||||
|
|
||||||
// residual = m.t()*w2*(m*tempCoeff-r);
|
|
||||||
// var temp0, temp1, residual mat.VecDense
|
|
||||||
// temp0.MulVec(M, &x)
|
|
||||||
// temp1.SubVec(&temp0, f)
|
|
||||||
// residual.MulVec(&MtW2, &temp1)
|
|
||||||
// var square mat.Dense
|
|
||||||
// square.Mul(residual.T(), &residual)
|
|
||||||
// residualValue := math.Sqrt(square.At(0, 0))
|
|
||||||
// if residualValue < 0.0001 {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fmt.Printf("residual value: %.16f\n", residualValue)
|
|
||||||
// fmt.Printf("iterations: %d\n", iterations)
|
|
||||||
|
|
||||||
e := 0.0
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
Rcal := project(numerator, denominator, latVec.AtVec(i), lonVec.AtVec(i), heightVec.AtVec(i))
|
|
||||||
e += math.Pow(Rcal-f.AtVec(i), 2)
|
|
||||||
}
|
|
||||||
e = math.Sqrt(e / float64(n))
|
|
||||||
fmt.Println("iterations:", iterations, "r error:", e)
|
|
||||||
|
|
||||||
if e < 1e-5 {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// dnum := mat.NewVecDense(20, nil)
|
x0 = x1
|
||||||
// b0, b1 := true, true
|
v0 = v
|
||||||
// dden := mat.NewVecDense(19, nil)
|
iterations++
|
||||||
// for i := 0; i < n; i++ {
|
|
||||||
// dnum.SetVec(i, math.Abs(numerator.AtVec(i)-numerator0.AtVec(i)))
|
|
||||||
// numerator0.SetVec(i, numerator.AtVec(i))
|
|
||||||
// fmt.Println("dnum:", i, dnum.AtVec(i))
|
|
||||||
// if dnum.AtVec(i) > 0.000001 {
|
|
||||||
// b0 = false
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for i := 1; i < n; i++ {
|
|
||||||
// dden.SetVec(i, math.Abs(denominator.AtVec(i)-denominator0.AtVec(i)))
|
|
||||||
// denominator0.SetVec(i, denominator.AtVec(i))
|
|
||||||
// if dden.AtVec(i) > 0.000001 {
|
|
||||||
// b1 = false
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if b0 && b1 {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("iterations:", iterations)
|
log.Println("iterations:", iterations)
|
||||||
|
if iterations == maxIterations {
|
||||||
|
sort.Slice(vx, func(i, j int) bool {
|
||||||
|
return vx[i].v < vx[j].v
|
||||||
|
})
|
||||||
|
x0 = vx[0].x
|
||||||
|
log.Printf("select min v-err: %.8f", vx[0].v)
|
||||||
|
}
|
||||||
|
|
||||||
return mat.Col(nil, 0, &x), nil
|
return mat.Col(nil, 0, &x0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupSystemOfEquations(Rn, latVec, lonVec, heightVec *mat.VecDense) *mat.Dense {
|
func setupSystemOfEquations(Rn, latVec, lonVec, heightVec *mat.VecDense) *mat.Dense {
|
||||||
@@ -152,7 +160,7 @@ func setupSystemOfEquations(Rn, latVec, lonVec, heightVec *mat.VecDense) *mat.De
|
|||||||
B.Set(i, 7, L*L)
|
B.Set(i, 7, L*L)
|
||||||
B.Set(i, 8, P*P)
|
B.Set(i, 8, P*P)
|
||||||
B.Set(i, 9, H*H)
|
B.Set(i, 9, H*H)
|
||||||
B.Set(i, 10, P*L*H)
|
B.Set(i, 10, L*P*H)
|
||||||
B.Set(i, 11, L*L*L)
|
B.Set(i, 11, L*L*L)
|
||||||
B.Set(i, 12, L*P*P)
|
B.Set(i, 12, L*P*P)
|
||||||
B.Set(i, 13, L*H*H)
|
B.Set(i, 13, L*H*H)
|
||||||
@@ -171,7 +179,7 @@ func setupSystemOfEquations(Rn, latVec, lonVec, heightVec *mat.VecDense) *mat.De
|
|||||||
B.Set(i, 26, -L*L*r)
|
B.Set(i, 26, -L*L*r)
|
||||||
B.Set(i, 27, -P*P*r)
|
B.Set(i, 27, -P*P*r)
|
||||||
B.Set(i, 28, -H*H*r)
|
B.Set(i, 28, -H*H*r)
|
||||||
B.Set(i, 29, -P*L*H*r)
|
B.Set(i, 29, -L*P*H*r)
|
||||||
B.Set(i, 30, -L*L*L*r)
|
B.Set(i, 30, -L*L*L*r)
|
||||||
B.Set(i, 31, -L*P*P*r)
|
B.Set(i, 31, -L*P*P*r)
|
||||||
B.Set(i, 32, -L*H*H*r)
|
B.Set(i, 32, -L*H*H*r)
|
||||||
@@ -206,7 +214,7 @@ func setupWeightMatrix(coeffs, latVec, lonVec, heightVec *mat.VecDense) *mat.Dia
|
|||||||
row.Set(i, 7, L*L)
|
row.Set(i, 7, L*L)
|
||||||
row.Set(i, 8, P*P)
|
row.Set(i, 8, P*P)
|
||||||
row.Set(i, 9, H*H)
|
row.Set(i, 9, H*H)
|
||||||
row.Set(i, 10, P*L*H)
|
row.Set(i, 10, L*P*H)
|
||||||
row.Set(i, 11, L*L*L)
|
row.Set(i, 11, L*L*L)
|
||||||
row.Set(i, 12, L*P*P)
|
row.Set(i, 12, L*P*P)
|
||||||
row.Set(i, 13, L*H*H)
|
row.Set(i, 13, L*H*H)
|
||||||
|
|||||||
64
pkg/producer/rpc_optimize.go
Normal file
64
pkg/producer/rpc_optimize.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package producer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gonum.org/v1/gonum/mat"
|
||||||
|
"gonum.org/v1/gonum/optimize"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NormElements struct {
|
||||||
|
LineOff, SampOff, LatOff, LonOff, HeightOff float64
|
||||||
|
LineScale, SampScale, LatScale, LonScale, HeightScale float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectiveFunc(numerator, denominator, f, latVec, lonVec, heightVec *mat.VecDense) float64 {
|
||||||
|
errorSquared := 0.0
|
||||||
|
n := f.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
predictedV := project(numerator, denominator, latVec.AtVec(i), lonVec.AtVec(i), heightVec.AtVec(i))
|
||||||
|
errorV := predictedV - f.AtVec(i)
|
||||||
|
errorSquared += errorV * errorV
|
||||||
|
}
|
||||||
|
return errorSquared / float64(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func solveNelderMead(num, den, f, latVec, lonVec, heightVec *mat.VecDense) (*mat.VecDense, *mat.VecDense, error) {
|
||||||
|
var initCoeffs []float64 // a0-a19,b1-b19
|
||||||
|
initCoeffs = append(initCoeffs, num.RawVector().Data...)
|
||||||
|
for i := 1; i < 20; i++ {
|
||||||
|
initCoeffs = append(initCoeffs, den.AtVec(i))
|
||||||
|
}
|
||||||
|
problem := optimize.Problem{
|
||||||
|
Func: func(coeffs []float64) float64 {
|
||||||
|
numerator := mat.NewVecDense(20, nil)
|
||||||
|
denominator := mat.NewVecDense(20, nil)
|
||||||
|
denominator.SetVec(0, 1.0)
|
||||||
|
numerator.SetVec(0, coeffs[0])
|
||||||
|
for i := 1; i < 20; i++ {
|
||||||
|
numerator.SetVec(i, coeffs[i])
|
||||||
|
denominator.SetVec(i, coeffs[i+19])
|
||||||
|
}
|
||||||
|
return objectiveFunc(numerator, denominator, f, latVec, lonVec, heightVec)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := optimize.Minimize(problem, initCoeffs, &optimize.Settings{}, &optimize.NelderMead{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in RPC optimization: ", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
numerator := mat.NewVecDense(20, nil)
|
||||||
|
denominator := mat.NewVecDense(20, nil)
|
||||||
|
denominator.SetVec(0, 1.0)
|
||||||
|
numerator.SetVec(0, result.X[0])
|
||||||
|
fmt.Println("len of result.X: ", len(result.X))
|
||||||
|
for i := 1; i < 20; i++ {
|
||||||
|
numerator.SetVec(i, result.X[i])
|
||||||
|
denominator.SetVec(i, result.X[i+19])
|
||||||
|
}
|
||||||
|
|
||||||
|
return numerator, denominator, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user