본문 바로가기
유도항법제어/최적제어

[PSOC-12] 예제 : 램버트 문제 (Lambert’s problem)

by 깊은대학 2023. 9. 23.

램버트 문제(Lambert's problem)는 이체문제(two-body problem)에서 유도된 기본 궤도 미분 방정식에 대한 2점 경계값 문제(TPBVP, two-point boundary value problem)이다.

 

(1)d2rdt2+μ(rr)3r=0r(t0)=r0,   r(tf)=rf,   t0, tf given

 

여기서 μ 는 중력 파라미터, r 은 관성좌표계의 원점에서 질점까지의 위치벡터다.

 

 

램버트 문제의 솔루션은 여러가지가 제안되어 있지만 여기서는 램버트 문제를 최적제어 문제로 변환시킨 후 로바토 유사 스펙트럴 방법(LPM)으로 풀어보고자 한다 (https://pasus.tistory.com/282).

 

 

램버트 문제를 최적제어 문제로 변환하면 다음과 같다 (https://pasus.tistory.com/268).

 

(2)argminvJ=t0tf(12vv+μrr) dt(3)subject to :  drdt=v(4)r(t0)=r0,   r(tf)=rf

 

이 예제에서는 다음 수치를 사용한다.

 

r0=[5,00010,0002,100]T kmrf=[14,6002,5007,000]T kmtft0=3,600 sec  (1 hr)μ=398,600 km3/s2R=6,378 km  (Earth radius)

 

그러면 구하고자 하는 램버트 문제의 정답은 다음과 같다.

 

v0=[5.992491.925363.24564]T km/svf=[3.312464.196620.38529]T km/s

 

과연 어느 정도의 정확도로 LPM이 답을 계산하는지 알아보도록 하자.

먼저 본 예제에서 사용하는 거리와 속도, 시간의 단위를 그대로 최적화에 사용하기에는 수치의 범위가 너무 크므로 천문단위를 이용하여 무차원화 시킨다 (https://pasus.tistory.com/183).

 

% parameters
mu_orig=398600; % mu=GM
DU=6378;
TU=DU^(3/2)/sqrt(mu_orig);
DUTU=DU/TU;

mu=1;
t0=0;

% problem formulation
tf_orig=60*60;

rr0_0=[5000 10000  2100]';
rrf_0=[-14600  2500  7000]';

rr0 = rr0_0/DU;
rrf = rrf_0/DU;
tf = tf_orig/TU;

 

여기서는 N=12 개의 LGL 콜로케이션 포인트를 사용한다. LGL 콜로케이션 포인트와 보간점, LGL 쿼드래처 포인트의 가중치(weighting) wj, 미분행렬 Dji 를 다음과 같이 계산한다.

 

% parameters for pseudospectral
N=12;  % number of collocation points
points=GaussPoints(N,'LGL'); % LGL collocation points (N)
col_point=points';
int_point=col_point; % interpolating points (N)
Dji=LagrangePolyDerivative(col_point,int_point); % Differentiation matrix
gweights=GaussianQuadrature(N,'LGL'); % LGL quadrature weights

 

LPM에서는 상태변수 r(τ) 와 제어변수 v(τ)(N1) 차 라그랑지 다항식으로 근사화한다.

 

r(τ)i=1NRiLi(τ)v(τ)i=1NViLi(τ)

 

목적함수 (2)는 다음과 같이 N 개의 LGL 포인트를 이용한 가우시안 쿼드래처로 근사화 된다.

 

J=(tft0)2j=1Nwj(12VjTVj+μRjTRj)

 

rsum=0;
for ii=1:N
    rsum=rsum+ww(ii)/sqrt(rr(ii,1)*rr(ii,1)+ ...
         rr(ii,2)*rr(ii,2)+rr(ii,3)*rr(ii,3)+ep);
end

vsum=(ww.*vv(:,1))'*vv(:,1)+(ww.*vv(:,2))'*vv(:,2)+(ww.*vv(:,3))'*vv(:,3);
rcost = (tf-t0)/2*((0.5*vsum)+mu*rsum);

 

식 (4)의 경계조건은 다음과 같다.

 

R1r0=0RNrf=0

 

% equality constraints
ceq = [rr(1,1)-param.rr0(1); 
       rr(1,2)-param.rr0(2); 
       rr(1,3)-param.rr0(3); 
       rr(Nitp,1)-param.rrf(1); 
       rr(Nitp,2)-param.rrf(2); 
       rr(Nitp,3)-param.rrf(3)  ];

 

식 (3)의 운동 미분방정식은 LGL 콜로케이션 포인트에 배치시켜 다음 식을 만족시키도록 한다.

 

[D11D1NDN1DNN][R1TRNT]=(tft0)2[V1TVNT]

 

% dynamic constraints  rr_dot=vv
F = vv;

for n=1:3 % state number
    ceq=[ceq;
         Dji*rr(:,n)-(tf-t0)/2*F(:,n)];
end

 

최적화 대상 변수는 다음과 같다.

 

(R1,R2,...,RN), (V1,V2,...,VN)

 

pinput_0 = [rr1_0; rr2_0; rr3_0; vv1_0; vv2_0; vv3_0];

 

 

 

이제 매트랩의 비선형 최적화 문제 솔버인 'fmincon' 함수를 이용하여 위 문제를 풀면 된다.

 

% Using MATLAB nonlinear optimization solved 'fmincon' 

Aineq = []; Bineq = []; % no linear inequality constraints
Aeq = []; Beq = []; % no equality constraints

LBx=-Inf*ones(3*Nitp,1);
UBx=Inf*ones(3*Nitp,1);

LBu=-Inf*ones(3*N,1);
UBu=Inf*ones(3*N,1);

LB = [LBx; LBu];  % lower bound on the unknown variables
UB = [UBx; UBu]; % upper bound on the unknown variables

options = optimset('display','iter','diffmaxchange',1.1*1e-7,'diffminchange',1e-7,'MaxFunEvals',50000);

[presult,optfval] = ...
    fmincon(@ExLambert_L_cost,pinput_0,Aineq,Bineq,Aeq,Beq,LB,UB,@ExLambert_L_cons,options,param);

 

 

결과는 다음과 같다.

 

V1=[5.992481.925353.24562]T km/sVN=[3.312494.196620.38531]T km/s

 

초기속도 오차의 크기는 0.0256 m/s, 최종속도 오차의 크기는 0.0285 m/s 로서 해가 정확함을 알 수 있다.

아래 그림은 궤도와 위치벡터, 속도벡터, 에너지의 궤적을 그린 것이다. 에너지가 일정하게 나오므로 LPM 으로 푼 램버트 문제의 해가 안정적임을 보여준다.

 

 

전체 매트랩 코드는 다음과 같다.

 

 

 

ExLambert_L_main.m

 

%
% Standard Lambert problem
%
% main
% using LGL pseudospectral method
% J= Lambert 
%
% Needs GaussPoints.m  LagrangePolyDerivative.m  GaussianQuadrature.m
%
% coded by st.watermelon
%

clear all; 
close all; % starting with a clean slate

% parameters
mu_orig=398600; % mu=GM
DU=6378;
TU=DU^(3/2)/sqrt(mu_orig);
DUTU=DU/TU;

mu=1;
t0=0;

% problem formulation
tf_orig=60*60;

rr0_0=[5000 10000  2100]';
rrf_0=[-14600  2500  7000]';

%----------- ref value -----------------
v0_orig = [-5.992494639666394 1.925363415280893 3.245636528490489]'; 
vf_orig = [-3.312460310936790 -4.196617307926468 -0.385287617068105]';
E_0 =(vf_orig'*vf_orig)/2-mu_orig/(sqrt(rrf_0'*rrf_0)); % specified energy
%----------- ref value -----------------

rr0=rr0_0/DU;
rrf = rrf_0/DU;
tf = tf_orig/TU;

% parameters for pseudospectral
N=12;  % number of collocation points
points=GaussPoints(N,'LGL'); % LGL collocation points (N)
col_point=points';
int_point=col_point; % interpolating points (N)
Dji=LagrangePolyDerivative(col_point,int_point); % Differentiation matrix
gweights=GaussianQuadrature(N,'LGL'); % LGL quadrature weights

% collecting parameters into param
param.Dji=Dji;
param.gweights=gweights;
param.N=N;
param.rr0=rr0;
param.rrf=rrf;
param.mu=mu;
param.t0=t0;
param.tf=tf;

% initial guesses for optimization variables (X and U)
Nitp=N;
rr1_0=zeros(Nitp,1); rr1_0(1)=rr0(1);
rr2_0=zeros(Nitp,1); rr2_0(1)=rr0(2);
rr3_0=zeros(Nitp,1); rr3_0(1)=rr0(3);

vv1_0=zeros(N,1); 
vv2_0=zeros(N,1); 
vv3_0=zeros(N,1); 

tf0=10;

% arrange initial guessed for the unknowns into a single vector
pinput_0 = [rr1_0; rr2_0; rr3_0; vv1_0; vv2_0; vv3_0];


% Using MATLAB nonlinear optimization solved 'fmincon' 

Aineq = []; Bineq = []; % no linear inequality constraints
Aeq = []; Beq = []; % no equality constraints

LBx=-Inf*ones(3*Nitp,1);
UBx=Inf*ones(3*Nitp,1);

LBu=-Inf*ones(3*N,1);
UBu=Inf*ones(3*N,1);

LB = [LBx; LBu];  % lower bound on the unknown variables
UB = [UBx; UBu]; % upper bound on the unknown variables

options = optimset('display','iter','diffmaxchange',1.1*1e-7,'diffminchange',1e-7,'MaxFunEvals',50000);

[presult,optfval] = ...
    fmincon(@ExLambert_L_cost,pinput_0,Aineq,Bineq,Aeq,Beq,LB,UB,@ExLambert_L_cons,options,param);

% results
rr1_res=presult(1:Nitp);
rr2_res=presult(Nitp+1:2*Nitp);
rr3_res=presult(2*Nitp+1:3*Nitp);

vv1_res=presult(3*Nitp+1:4*Nitp);
vv2_res=presult(4*Nitp+1:5*Nitp);
vv3_res=presult(5*Nitp+1:6*Nitp);


% Lagrange interpolating polynomials
tau=linspace(-1,1,300)';
dataset_rr1=[int_point' rr1_res];
dataset_rr2=[int_point' rr2_res];
dataset_rr3=[int_point' rr3_res];
dataset_vv1=[col_point' vv1_res]; % no u at 1 (final point)
dataset_vv2=[col_point' vv2_res]; 
dataset_vv3=[col_point' vv3_res]; 

p_rr1=LagrangePoly(dataset_rr1,tau);
p_rr2=LagrangePoly(dataset_rr2,tau);
p_rr3=LagrangePoly(dataset_rr3,tau);
p_vv1=LagrangePoly(dataset_vv1,tau);
p_vv2=LagrangePoly(dataset_vv2,tau);
p_vv3=LagrangePoly(dataset_vv3,tau);

tt=((tf-t0)*tau+(tf+t0))/2*TU; % convert to t from tau

% plotting
figure,plot(((tf-t0)*dataset_rr1(:,1)+(tf+t0))/2*TU,dataset_rr1(:,2)*DU,'ro', ...
            ((tf-t0)*dataset_rr2(:,1)+(tf+t0))/2*TU,dataset_rr2(:,2)*DU,'go', ...
            ((tf-t0)*dataset_rr3(:,1)+(tf+t0))/2*TU,dataset_rr3(:,2)*DU,'bo',...
            tt,p_rr1*DU,'r', tt,p_rr2*DU,'g', tt,p_rr3*DU,'b')
legend('r1','r2','r3')
grid

figure,plot(((tf-t0)*dataset_vv1(:,1)+(tf+t0))/2*TU,dataset_vv1(:,2)*DUTU,'ro', ...
            ((tf-t0)*dataset_vv2(:,1)+(tf+t0))/2*TU,dataset_vv2(:,2)*DUTU,'go', ...
            ((tf-t0)*dataset_vv3(:,1)+(tf+t0))/2*TU,dataset_vv3(:,2)*DUTU,'bo', ...
            tt,p_vv1*DUTU,'r',tt,p_vv2*DUTU,'g', tt,p_vv3*DUTU,'b')
legend('v1','v2','v3')
grid
        
figure, plot3(dataset_rr1(:,2)*DU,dataset_rr2(:,2)*DU,dataset_rr3(:,2)*DU,'ro',...
              p_rr1*DU,p_rr2*DU,p_rr3*DU, 'r', 0,0,0,'go', ...
              dataset_rr1(1,2)*DU,dataset_rr2(1,2)*DU,dataset_rr3(1,2)*DU,'b*');
          xlabel('x');ylabel('y');zlabel('z'); grid

          
          
Ener = ((dataset_vv1(:,2)).^2+(dataset_vv2(:,2)).^2 + ...
          (dataset_vv3(:,2)).^2).*(DUTU)^2./2 -  ...
          mu_orig./(DU.*sqrt(((dataset_rr1(1:N,2)).^2+(dataset_rr2(1:N,2)).^2 + ...
          (dataset_rr3(1:N,2)).^2)));
figure, plot(((tf-t0)*dataset_vv1(:,1)+(tf+t0))/2*TU, Ener,'bo');
          xlabel('time(sec)');ylabel('Ener'); grid
          
format long

disp('ref vs computed initial velocity......................');
VV0=[dataset_vv1(1,2) dataset_vv2(1,2) dataset_vv3(1,2)]'*DUTU;
[v0_orig VV0]
disp('ref vf vs computed vf......................');
VVf = [dataset_vv1(end,2); dataset_vv2(end,2); dataset_vv3(end,2)]*DUTU;
[vf_orig VVf]
disp('errors of initial and final velocity......................');
norm(v0_orig-VV0)
norm(vf_orig-VVf)
disp('ref Energy vs computed Energy......................');
RR0=[dataset_rr1(1,2) dataset_rr2(1,2) dataset_rr3(1,2)]*DU;
[E_0 (norm(VV0))^2/2-mu_orig/norm(RR0)]

 

ExLambert_L_cost.m

 

%
% Standard Lambert problem
%
% Cost function
%
% coded by st.watermelon
%

function rcost = ExLambert_L_cost(pinput,param)

ww=param.gweights;
N=param.N;
mu=param.mu;
t0=param.t0;
tf=param.tf;

Nitp=N;

ep=1e-10;

rr(:,1)=pinput(1:Nitp);
rr(:,2)=pinput(Nitp+1:2*Nitp);
rr(:,3)=pinput(2*Nitp+1:3*Nitp);

vv(:,1)=pinput(3*Nitp+1:4*Nitp);
vv(:,2)=pinput(4*Nitp+1:5*Nitp);
vv(:,3)=pinput(5*Nitp+1:6*Nitp);

rsum=0;
for ii=1:N
    rsum=rsum+ww(ii)/sqrt(rr(ii,1)*rr(ii,1)+ ...
         rr(ii,2)*rr(ii,2)+rr(ii,3)*rr(ii,3)+ep);
end

vsum=(ww.*vv(:,1))'*vv(:,1)+(ww.*vv(:,2))'*vv(:,2)+(ww.*vv(:,3))'*vv(:,3);
rcost = (tf-t0)/2*((0.5*vsum)+mu*rsum);

 

ExLambert_L_cons.m

 

%
% Standard Lambert problem
%
% Constraints
%
% coded by st.watermelon
%

function [cineq,ceq] = ExLambert_L_cons(pinput,param)
%
% constraints
%
N=param.N;
Dji=param.Dji;
t0=param.t0;
tf=param.tf;

Nitp=N;

rr(:,1)=pinput(1:Nitp);
rr(:,2)=pinput(Nitp+1:2*Nitp);
rr(:,3)=pinput(2*Nitp+1:3*Nitp);

vv(:,1)=pinput(3*Nitp+1:4*Nitp);
vv(:,2)=pinput(4*Nitp+1:5*Nitp);
vv(:,3)=pinput(5*Nitp+1:6*Nitp);


% inequality constraints
cineq = []; 

% dynamic constraints  rr_dot=vv
F = vv;
      
% equality constraints
ceq = [rr(1,1)-param.rr0(1); 
       rr(1,2)-param.rr0(2); 
       rr(1,3)-param.rr0(3); 
       rr(Nitp,1)-param.rrf(1); 
       rr(Nitp,2)-param.rrf(2); 
       rr(Nitp,3)-param.rrf(3)  ];
      

for n=1:3 % state number
    ceq=[ceq;
         Dji*rr(:,n)-(tf-t0)/2*F(:,n)];
end

 

 

댓글