415415 @test ukf9. R̂ ≈ I (2 )
416416
417417 linmodel2 = LinModel {Float32} (0.5 * ones (1 ,1 ), ones (1 ,1 ), ones (1 ,1 ), zeros (1 ,0 ), zeros (1 ,0 ), 1.0 )
418- ukf9 = UnscentedKalmanFilter (linmodel2)
419- @test isa (ukf9 , UnscentedKalmanFilter{Float32})
418+ ukf10 = UnscentedKalmanFilter (linmodel2)
419+ @test isa (ukf10 , UnscentedKalmanFilter{Float32})
420420end
421421
422422@testset " UnscentedKalmanFilter estimator methods" begin
@@ -547,3 +547,148 @@ end
547547 @test x̂ ≈ [0 , 0 ]
548548 @test isa (x̂, Vector{Float32})
549549end
550+
551+ @testset " MovingHorizonEstimator construction" begin
552+ linmodel1 = LinModel (sys,Ts,i_d= [3 ])
553+ f (x,u,d) = linmodel1. A* x + linmodel1. Bu* u + linmodel1. Bd* d
554+ h (x,d) = linmodel1. C* x + linmodel1. Du* d
555+ nonlinmodel = NonLinModel (f, h, Ts, 2 , 4 , 2 , 1 )
556+
557+ mhe1 = MovingHorizonEstimator (linmodel1, He= 5 )
558+ @test mhe1. nym == 2
559+ @test mhe1. nyu == 0
560+ @test mhe1. nxs == 2
561+ @test mhe1. nx̂ == 6
562+
563+ mhe2 = MovingHorizonEstimator (nonlinmodel, He= 5 )
564+ @test mhe2. nym == 2
565+ @test mhe2. nyu == 0
566+ @test mhe2. nxs == 2
567+ @test mhe2. nx̂ == 6
568+
569+ mhe3 = MovingHorizonEstimator (nonlinmodel, He= 5 , i_ym= [2 ])
570+ @test mhe3. nym == 1
571+ @test mhe3. nyu == 1
572+ @test mhe3. nxs == 1
573+ @test mhe3. nx̂ == 5
574+
575+ mhe4 = MovingHorizonEstimator (nonlinmodel, He= 5 , σQ= [1 ,2 ,3 ,4 ], σQint_ym= [5 , 6 ], σR= [7 , 8 ])
576+ @test mhe4. Q̂ ≈ Hermitian (diagm (Float64[1 , 4 , 9 ,16 , 25 , 36 ]))
577+ @test mhe4. R̂ ≈ Hermitian (diagm (Float64[49 , 64 ]))
578+
579+ mhe5 = MovingHorizonEstimator (nonlinmodel, He= 5 , nint_ym= [2 ,2 ])
580+ @test mhe5. nxs == 4
581+ @test mhe5. nx̂ == 8
582+
583+ mhe6 = MovingHorizonEstimator (nonlinmodel, He= 5 , σP0= [1 ,2 ,3 ,4 ], σP0int_ym= [5 ,6 ])
584+ @test mhe6. P̂0 ≈ Hermitian (diagm (Float64[1 , 4 , 9 ,16 , 25 , 36 ]))
585+ @test mhe6. P̂ ≈ Hermitian (diagm (Float64[1 , 4 , 9 ,16 , 25 , 36 ]))
586+ @test mhe6. P̂0 != = mhe6. P̂
587+
588+ mhe7 = MovingHorizonEstimator (nonlinmodel, He= 10 )
589+ @test mhe7. He == 10
590+ @test length (mhe7. X̂) == 10 * 6
591+ @test length (mhe7. Ym) == 10 * 2
592+ @test length (mhe7. U) == 10 * 2
593+ @test length (mhe7. D) == 10 * 1
594+ @test length (mhe7. Ŵ) == 10 * 6
595+
596+ mhe8 = MovingHorizonEstimator (nonlinmodel, He= 5 , nint_u= [1 , 1 ], nint_ym= [0 , 0 ])
597+ @test mhe8. nxs == 2
598+ @test mhe8. nx̂ == 6
599+ @test mhe8. nint_u == [1 , 1 ]
600+ @test mhe8. nint_ym == [0 , 0 ]
601+
602+ mhe9 = MovingHorizonEstimator (nonlinmodel, 5 , 1 : 2 , 0 , [1 , 1 ], I (6 ), I (6 ), I (2 ), Model (Ipopt. Optimizer))
603+ @test mhe9. P̂0 ≈ I (6 )
604+ @test mhe9. Q̂ ≈ I (6 )
605+ @test mhe9. R̂ ≈ I (2 )
606+
607+ mhe10 = MovingHorizonEstimator (nonlinmodel, He= 5 , optim= Model (OSQP. Optimizer))
608+ @test solver_name (mhe10. optim) == " OSQP"
609+
610+ linmodel2 = LinModel {Float32} (0.5 * ones (1 ,1 ), ones (1 ,1 ), ones (1 ,1 ), zeros (1 ,0 ), zeros (1 ,0 ), 1.0 )
611+ mhe11 = MovingHorizonEstimator (linmodel2, He= 5 )
612+ @test isa (mhe11, MovingHorizonEstimator{Float32})
613+
614+ @test_throws ArgumentError MovingHorizonEstimator (linmodel1)
615+ @test_throws ArgumentError MovingHorizonEstimator (linmodel1, He= 0 )
616+ end
617+
618+ @testset " MovingHorizonEstimator estimator methods" begin
619+ linmodel1 = LinModel (sys,Ts,i_u= [1 ,2 ])
620+ f (x,u,_) = linmodel1. A* x + linmodel1. Bu* u
621+ h (x,_) = linmodel1. C* x
622+ nonlinmodel = setop! (NonLinModel (f, h, Ts, 2 , 2 , 2 ), uop= [10 ,50 ], yop= [50 ,30 ])
623+ mhe1 = MovingHorizonEstimator (nonlinmodel, He= 2 )
624+ @test updatestate! (mhe1, [10 , 50 ], [50 , 30 ]) ≈ zeros (4 ) atol= 1e-9
625+ @test updatestate! (mhe1, [10 , 50 ], [50 , 30 ], Float64[]) ≈ zeros (4 ) atol= 1e-9
626+ @test mhe1. x̂ ≈ zeros (4 ) atol= 1e-9
627+ @test evaloutput (mhe1) ≈ mhe1 () ≈ [50 , 30 ]
628+ @test evaloutput (mhe1, Float64[]) ≈ mhe1 (Float64[]) ≈ [50 , 30 ]
629+ @test initstate! (mhe1, [10 , 50 ], [50 , 30 + 1 ]) ≈ zeros (4 ) atol= 1e-9
630+ setstate! (mhe1, [1 ,2 ,3 ,4 ])
631+ @test mhe1. x̂ ≈ [1 ,2 ,3 ,4 ]
632+ for i in 1 : 100
633+ updatestate! (mhe1, [11 , 52 ], [50 , 30 ])
634+ end
635+ @test mhe1 () ≈ [50 , 30 ] atol= 1e-3
636+ for i in 1 : 100
637+ updatestate! (mhe1, [10 , 50 ], [51 , 32 ])
638+ end
639+ @test mhe1 () ≈ [51 , 32 ] atol= 1e-3
640+ mhe2 = MovingHorizonEstimator (linmodel1, He= 2 , nint_u= [1 , 1 ], nint_ym= [0 , 0 ])
641+ for i in 1 : 100
642+ updatestate! (mhe2, [11 , 52 ], [50 , 30 ])
643+ end
644+ @test mhe2 () ≈ [50 , 30 ] atol= 1e-3
645+ for i in 1 : 100
646+ updatestate! (mhe2, [10 , 50 ], [51 , 32 ])
647+ end
648+ @test mhe2 () ≈ [51 , 32 ] atol= 1e-3
649+ linmodel3 = LinModel {Float32} (0.5 * ones (1 ,1 ), ones (1 ,1 ), ones (1 ,1 ), zeros (1 ,0 ), zeros (1 ,0 ), 1.0 )
650+ mhe3 = MovingHorizonEstimator (linmodel3, He= 1 )
651+ x̂ = updatestate! (mhe3, [0 ], [0 ])
652+ @test x̂ ≈ [0 , 0 ] atol= 1e-3
653+ @test isa (x̂, Vector{Float32})
654+
655+ mhe4 = setconstraint! (MovingHorizonEstimator (nonlinmodel, He= 1 , nint_ym= 0 ), x̂max= [50 ,50 ])
656+ g_X̂max_end = mhe4. optim. nlp_model. operators. registered_multivariate_operators[end ]. f
657+ @test g_X̂max_end ((1.0 , 1.0 , 1.0 , 1.0 )) ≤ 0.0 # test gfunc_i(i,::NTuple{N, Float64})
658+ # test gfunc_i(i,::NTuple{N, ForwardDiff.Dual}) :
659+ @test ForwardDiff. gradient (g_X̂max_end, [1.0 , 1.0 , 1.0 , 1.0 ]) ≈ [0.0 , 0.0 , 0.0 , 0.0 ]
660+ end
661+
662+ @testset " MovingHorizonEstimator set constraints" begin
663+ linmodel1 = setop! (LinModel (sys,Ts,i_u= [1 ,2 ]), uop= [10 ,50 ], yop= [50 ,30 ])
664+ mhe1 = MovingHorizonEstimator (linmodel1, He= 1 , nint_ym= 0 )
665+ setconstraint! (mhe1, x̂min= [- 51 ,- 52 ], x̂max= [53 ,54 ])
666+ @test all ((mhe1. X̂min, mhe1. X̂max) .≈ ([- 51 ,- 52 ,- 51 ,- 52 ], [53 ,54 ,53 ,54 ]))
667+
668+ mhe2 = MovingHorizonEstimator (linmodel1, He= 4 , nint_ym= 0 )
669+ setconstraint! (mhe2, X̂min= - 1 (1 : 10 ), X̂max= 1 (1 : 10 ))
670+ @test all ((mhe2. X̂min, mhe2. X̂max) .≈ (- 1 (1 : 10 ), 1 (1 : 10 )))
671+
672+ @test_throws ArgumentError setconstraint! (mhe2, x̂min= [- 1 ])
673+ @test_throws ArgumentError setconstraint! (mhe2, x̂max= [+ 1 ])
674+
675+ updatestate! (mhe1, [10 , 50 ], [50 , 30 ])
676+ @test_throws ErrorException setconstraint! (mhe1, x̂min= [- Inf ,- Inf ])
677+ @test_throws ErrorException setconstraint! (mhe1, x̂max= [+ Inf ,+ Inf ])
678+ end
679+
680+ @testset " MovingHorizonEstimator constraint violation" begin
681+ linmodel1 = LinModel (sys,Ts,i_u= [1 ,2 ])
682+ f (x,u,_) = linmodel1. A* x + linmodel1. Bu* u
683+ h (x,_) = linmodel1. C* x
684+ nonlinmodel = setop! (NonLinModel (f, h, Ts, 2 , 2 , 2 ), uop= [10 ,50 ], yop= [50 ,30 ])
685+ mhe = MovingHorizonEstimator (nonlinmodel, He= 1 , nint_ym= 0 )
686+
687+ setconstraint! (mhe, x̂min= [1 ,1 ], x̂max= [100 ,100 ])
688+ x̂ = updatestate! (mhe, [10 , 50 ], [50 , 30 ])
689+ @test x̂ ≈ [1 , 1 ] atol= 1e-3
690+
691+ setconstraint! (mhe, x̂min= [- 100 ,- 100 ], x̂max= [- 1 ,- 1 ])
692+ x̂ = updatestate! (mhe, [10 , 50 ], [50 , 30 ])
693+ @test x̂ ≈ [- 1 , - 1 ] atol= 1e-3
694+ end
0 commit comments