Skip to content

Commit 653df14

Browse files
committed
All files added
1 parent 8c573e8 commit 653df14

14 files changed

+720
-0
lines changed
873 KB
Binary file not shown.
897 KB
Binary file not shown.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
%--------------------------------------------------------------------------
2+
% Bryson_Denham_collocation.m
3+
% This file solves the Bryson-Denham problem by
4+
% direct collocation method using Casadi
5+
%--------------------------------------------------------------------------
6+
% Primary Contributor: Nakul Randad, Indian Institute of Technology Bombay
7+
%--------------------------------------------------------------------------
8+
% CasADi v3.5.5
9+
import casadi.*
10+
11+
close all
12+
% clc
13+
14+
%% Set up collocation points
15+
% Degree of interpolating polynomial
16+
d = 3;
17+
18+
% Get collocation points
19+
tau = collocation_points(d, 'legendre');
20+
21+
% Collocation linear maps
22+
[C,D,B] = collocation_coeff(tau);
23+
24+
%% Declare decision variables
25+
T = 1; % Time horizon
26+
limit = 1/9; % position limit
27+
28+
% Declare model variables
29+
x1 = SX.sym('x1'); % position
30+
x2 = SX.sym('x2'); % velocity
31+
x = [x1; x2];
32+
u = SX.sym('u');
33+
34+
%% Dynamics and Objective
35+
% Model equations
36+
xdot = [x2; u];
37+
38+
% Objective term
39+
L = u^2/2;
40+
41+
% Continuous time dynamics
42+
f = Function('f', {x, u}, {xdot, L});
43+
44+
%% Control discretization
45+
N = 100; % number of control intervals
46+
h = T/N;
47+
48+
%% Set up solver
49+
% Start with an empty NLP
50+
51+
opti = Opti();
52+
J = 0;
53+
54+
% Initial conditions
55+
Xk = opti.variable(2);
56+
opti.subject_to(Xk==[0; 1]);
57+
opti.set_initial(Xk, [0; 1]);
58+
59+
% Collect all states/controls
60+
Xs = {Xk};
61+
Us = {};
62+
cost = [];
63+
64+
% Formulate the NLP
65+
for k=0:N-1
66+
% New NLP variable for the control
67+
Uk = opti.variable();
68+
Us{end+1} = Uk;
69+
opti.set_initial(Uk, 0);
70+
71+
% Decision variables for helper states at each collocation point
72+
Xc = opti.variable(2, d);
73+
opti.subject_to(Xc(1,:) <= limit); % inequality constraint on state
74+
opti.set_initial(Xc, repmat([0;0],1,d));
75+
76+
% Evaluate ODE right-hand-side at all helper states
77+
[ode, quad] = f(Xc, Uk);
78+
79+
% Add contribution to quadrature function
80+
int_L = quad*B*h;
81+
J = J + int_L;
82+
cost = [cost; J];
83+
84+
% Get interpolating points of collocation polynomial
85+
Z = [Xk Xc];
86+
87+
% Get slope of interpolating polynomial (normalized)
88+
Pidot = Z*C;
89+
% Match with ODE right-hand-side
90+
opti.subject_to(Pidot == h*ode);
91+
92+
% State at end of collocation interval
93+
Xk_end = Z*D;
94+
95+
% New decision variable for state at end of interval
96+
Xk = opti.variable(2);
97+
Xs{end+1} = Xk;
98+
opti.subject_to(Xk(1) <= limit);% inequality constraint on state
99+
opti.set_initial(Xk, [0;0]);
100+
101+
% Continuity constraints
102+
opti.subject_to(Xk_end==Xk)
103+
end
104+
105+
% Boundary conditions
106+
opti.subject_to(Xs{end}(1)==0);
107+
opti.subject_to(Xs{end}(2)==-1);
108+
109+
%% Optimisation solver
110+
111+
Xs = [Xs{:}];
112+
Us = [Us{:}];
113+
114+
opti.minimize(J); % minimise the objective function
115+
116+
opti.solver('ipopt'); % backend NLP solver
117+
118+
tic
119+
sol = opti.solve(); % Solve actual problem
120+
toc
121+
122+
x_opt = sol.value(Xs);
123+
u_opt = sol.value(Us);
124+
cost_opt = sol.value(cost);
125+
126+
%% Post-processing
127+
time = linspace(0, T, N+1);
128+
t = tiledlayout(2,2);
129+
t.Padding = 'compact';
130+
t.TileSpacing = 'compact';
131+
132+
nexttile
133+
hold on
134+
plot(time,x_opt(1,:),'b','LineWidth',1);
135+
yline(limit,'k--','LineWidth',1);
136+
hold off
137+
ylim([-inf, limit*1.05])
138+
ylabel('Position');
139+
xlabel('Time [s]');
140+
legend('x','$x < \frac{1}{9}$','Interpreter','latex','Location', 'South');
141+
142+
nexttile
143+
plot(time, x_opt(2,:),'Color',[0, 0.5, 0],'LineWidth',1);
144+
ylabel('Speed');
145+
xlabel('Time [s]');
146+
legend('v','Location', 'South')
147+
148+
nexttile
149+
plot(time, [u_opt nan],'r','LineWidth',1);
150+
xlabel('Time [s]');
151+
ylabel('Thrust');
152+
legend('u','Location', 'South');
153+
154+
nexttile
155+
plot(time,[cost_opt; nan],'--','LineWidth',1);
156+
xlabel('Time [s]');
157+
ylabel('Objective');
158+
legend('$\frac{1}{2} \int u^2$','Interpreter','latex','Location', 'South');
159+
160+
% To print the figure
161+
% print('./results/optimal_sol_collocation','-dpng')
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
%--------------------------------------------------------------------------
2+
% Bryson_Denham_multiple_shooting.m
3+
% This file solves the Bryson-Denham problem by
4+
% multiple-shooting method using Casadi
5+
%--------------------------------------------------------------------------
6+
% Primary Contributor: Nakul Randad, Indian Institute of Technology Bombay
7+
%--------------------------------------------------------------------------
8+
% CasADi v3.5.5
9+
import casadi.*
10+
11+
close all
12+
% clc
13+
14+
%% Setting up the problem
15+
N = 100; % number of control intervals
16+
opti = casadi.Opti(); % Optimization problem
17+
18+
%% Declare decision variables
19+
X = opti.variable(2,N+1); % state trajectory
20+
pos = X(1,:);
21+
speed = X(2,:);
22+
U = opti.variable(1,N); % control trajectory (throttle)
23+
T = 1; % final time
24+
limit = 1/9; % position limit
25+
time = linspace(0, T, N+1)'; % time horizon
26+
27+
%% Set up the objective
28+
L = U.^2/2; % integrand
29+
dt = T/N; % length of a control interval
30+
cost = [];
31+
obj = 0;
32+
for i = 1:N
33+
obj = obj + L(i)*dt;
34+
cost = [cost;obj];
35+
end
36+
opti.minimize(obj); % minimize objective
37+
38+
%% System dynamics
39+
f = @(x,u) [x(2);u]; % dx/dt = f(x,u)
40+
41+
%% Numerical integration and constraint to make zero gap
42+
for k=1:N % loop over control intervals
43+
% Runge-Kutta 4 integration
44+
k1 = f(X(:,k), U(:,k));
45+
k2 = f(X(:,k)+dt/2*k1, U(:,k));
46+
k3 = f(X(:,k)+dt/2*k2, U(:,k));
47+
k4 = f(X(:,k)+dt*k3, U(:,k));
48+
x_next = X(:,k) + dt/6*(k1+2*k2+2*k3+k4);
49+
opti.subject_to(X(:,k+1)==x_next); % close the gaps
50+
end
51+
52+
%% Path constraints
53+
opti.subject_to(pos<=limit); % position limit
54+
55+
%% Boundary conditions
56+
opti.subject_to(pos(1)==0); % start at position 0
57+
opti.subject_to(speed(1)==1);
58+
opti.subject_to(pos(N+1)==0); % finish line at position 0
59+
opti.subject_to(speed(N+1)==-1);
60+
61+
%% Initial guess
62+
opti.set_initial(speed, 1);
63+
opti.set_initial(pos, 0);
64+
65+
%% Solver set up
66+
opti.solver('ipopt'); % set numerical backend
67+
tic
68+
sol = opti.solve(); % actual solve
69+
toc
70+
71+
%% Post-processing
72+
t = tiledlayout(2,2);
73+
t.Padding = 'compact';
74+
t.TileSpacing = 'compact';
75+
76+
nexttile
77+
hold on
78+
plot(time,sol.value(pos),'b','LineWidth',1);
79+
yline(limit,'k--','LineWidth',1);
80+
hold off
81+
ylim([-inf, limit*1.05])
82+
ylabel('Position');
83+
xlabel('Time [s]');
84+
legend('x','$x < \frac{1}{9}$','Interpreter','latex','Location', 'South');
85+
86+
nexttile
87+
plot(time,sol.value(speed),'Color',[0, 0.5, 0],'LineWidth',1);
88+
ylabel('Speed');
89+
xlabel('Time [s]');
90+
legend('v','Location', 'South')
91+
92+
nexttile
93+
stairs(time(1:end-1),sol.value(U),'r','LineWidth',1);
94+
xlabel('Time [s]');
95+
ylabel('Thrust');
96+
legend('u','Location', 'South');
97+
98+
nexttile
99+
plot(time(1:end-1),sol.value(cost),'--','LineWidth',1);
100+
xlabel('Time [s]');
101+
ylabel('Objective');
102+
legend('$\frac{1}{2} \int u^2$','Interpreter','latex','Location', 'South');
103+
104+
% To print the figure
105+
% print('./results/optimal_sol_multiple_shooting','-dpng')
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
%--------------------------------------------------------------------------
2+
% Bryson_Denham_single_shooting.m
3+
% This file solves the Bryson-Denham problem by single-shooting method
4+
% using fmincon
5+
% (employs the trapezodial rule with composite trapezoidal quadrature)
6+
%--------------------------------------------------------------------------
7+
% Primary Contributor: Nakul Randad, Indian Institute of Technology Bombay
8+
%--------------------------------------------------------------------------
9+
10+
soln = method();
11+
12+
% actual implementation
13+
function soln = method
14+
% problem parameters
15+
p.ns = 2; p.nu = 1; % number of states and controls
16+
p.t0 = 0; p.tf = 1; % time horizon
17+
p.y10 = 0; p.y1f = 0; p.y20 = 1; p.y2f = -1; % boundary conditions
18+
p.l = 1/9;
19+
20+
% direct transcription parameters
21+
% p.nt = 20; % number of node points
22+
p.nt = 100; % number of node points
23+
p.t = linspace(p.t0,p.tf,p.nt)'; % time horizon
24+
p.h = diff(p.t); % step size
25+
26+
% discretized variable indices in x = [y1,y2,u];
27+
p.y1i = 1:p.nt; p.y2i = p.nt+1:2*p.nt; p.ui = 2*p.nt+1:3*p.nt;
28+
x0 = zeros(p.nt*(p.ns+p.nu),1); % initial guess (all zeros)
29+
options = optimoptions(@fmincon,'display','iter','MaxFunEvals',1e5); % options
30+
31+
% solve the problem
32+
tic
33+
x = fmincon(@(x) objective(x,p),x0,[],[],[],[],[],[],@(x) constraints(x,p),options);
34+
toc
35+
36+
% obtain the optimal solution
37+
y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract
38+
soln.y1 = y1; soln.y2 = y2; soln.u = u; soln.p = p;
39+
40+
% plots
41+
showPlot(y1,y2,u,p)
42+
end
43+
44+
% objective function
45+
function f = objective(x,p)
46+
u = x(p.ui); % extract
47+
L = u.^2/2; % integrand
48+
f = trapz(p.t,L); % calculate objective
49+
end
50+
51+
% constraint function
52+
function [c,ceq] = constraints(x,p)
53+
y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract
54+
Y = [y1,y2]; F = [y2,u]; % create matrices (p.nt x p.ns)
55+
ceq1 = y1(1) - p.y10; % initial state conditions
56+
ceq2 = y2(1) - p.y20;
57+
ceq3 = y1(end) - p.y1f; % final state conditions
58+
ceq4 = y2(end) - p.y2f;
59+
60+
% integrate using trapezoidal quadrature
61+
ceq5 = Y(2:p.nt,1) - Y(1:p.nt-1,1) - p.h/2.*( F(1:p.nt-1,1) + F(2:p.nt,1) );
62+
ceq6 = Y(2:p.nt,2) - Y(1:p.nt-1,2) - p.h/2.*( F(1:p.nt-1,2) + F(2:p.nt,2) );
63+
c1 = y1 - p.l; % path constraints
64+
65+
c = c1; ceq = [ceq1;ceq2;ceq3;ceq4;ceq5;ceq6]; % combine constraints
66+
end
67+
68+
% plotting function
69+
function showPlot(y1,y2,u,p)
70+
close all
71+
t = tiledlayout(2,2);
72+
t.Padding = 'compact';
73+
t.TileSpacing = 'compact';
74+
75+
nexttile
76+
hold on
77+
plot(p.t,y1,'b','LineWidth',1);
78+
yline(p.l,'k--','LineWidth',1);
79+
scatter(p.t0,p.y10,[],'g','filled');
80+
scatter(p.tf,p.y1f,[],'r','filled');
81+
hold off
82+
ylim([-inf, p.l*1.05])
83+
ylabel('Position');
84+
xlabel('Time [s]');
85+
legend('$y1$','$y1 < \frac{1}{9}$',"$y1_0$","$y1_f$",'Interpreter','latex','Location', 'South');
86+
87+
nexttile
88+
hold on
89+
plot(p.t,y2,'Color',[0, 0.5, 0],'LineWidth',1);
90+
scatter(p.t0,p.y20,[],'g','filled');
91+
scatter(p.tf,p.y2f,[],'r','filled');
92+
hold off
93+
ylabel('Speed');
94+
xlabel('Time [s]');
95+
legend('$y2$',"$y2_0$","$y2_f$",'Interpreter','latex','Location', 'South')
96+
97+
nexttile(3,[1,2])
98+
stairs(p.t,u,'r','LineWidth',1);
99+
xlabel('Time [s]');
100+
ylabel('Thrust');
101+
legend('u','Location', 'South');
102+
103+
% To print the figure
104+
% print('./results/optimal_sol_single_shooting','-dpng')
105+
end
39 KB
Loading
38.7 KB
Loading
36.6 KB
Loading

0 commit comments

Comments
 (0)