├── INSTALL_Direct_Method_Examples.m ├── License ├── README.md ├── include └── .gitignore ├── optional ├── .gitignore ├── Method_DTQPProject.m └── readme_image.svg └── src ├── Method_Pseudospectral.m ├── Method_SingleShooting.m ├── Method_SingleStep.m ├── Plots.m ├── Run_All_Examples.m └── bryson-denham ├── BrysonDenham_Solution_Control.m ├── BrysonDenham_Solution_States.m ├── BrysonDenham_formulation.svg └── BrysonDenham_solution.svg /INSTALL_Direct_Method_Examples.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % INSTALL_Direct_Method_Examples 3 | % This scripts helps you get the project up and running 4 | %-------------------------------------------------------------------------- 5 | % Automatically adds project files to your MATLAB path, downloads the 6 | % required files, and opens an example 7 | %-------------------------------------------------------------------------- 8 | % Install script based on MFX Submission Install Utilities 9 | % https://github.com/danielrherber/mfx-submission-install-utilities 10 | % https://www.mathworks.com/matlabcentral/fileexchange/62651 11 | %-------------------------------------------------------------------------- 12 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 13 | % Illinois at Urbana-Champaign 14 | % https://github.com/danielrherber/optimal-control-direct-method-examples 15 | %-------------------------------------------------------------------------- 16 | function INSTALL_Direct_Method_Examples 17 | 18 | % add contents to path 19 | AddSubmissionContents(mfilename) 20 | 21 | % download required web zips 22 | RequiredWebZips 23 | 24 | % add contents to path (files have been downloaded) 25 | AddSubmissionContents(mfilename) 26 | 27 | % run install file for DTQP Project 28 | evalc('INSTALL_DTQP'); 29 | CloseThisFile('BrysonHo166') 30 | 31 | % add contents to path (files have been downloaded) 32 | AddSubmissionContents(mfilename) 33 | 34 | % open example 35 | OpenThisFile('Run_All_Examples') 36 | 37 | % close this file 38 | CloseThisFile(mfilename) % this will close this file 39 | 40 | end 41 | %-------------------------------------------------------------------------- 42 | function RequiredWebZips 43 | disp('--- Obtaining required web zips') 44 | 45 | % initialize index 46 | ind = 0; 47 | 48 | % initialize structure 49 | zips = struct('url','','folder','','test',''); 50 | 51 | % zip 1 52 | ind = ind + 1; 53 | zips(ind).url = 'https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/51104/versions/1/download/zip/v1.zip'; 54 | zips(ind).folder = 'MFX 51104'; 55 | zips(ind).test = 'LagrangeInter'; 56 | 57 | % zip 2 58 | ind = ind + 1; % increment 59 | zips(ind).url = 'https://github.com/danielrherber/dt-qp-project/archive/master.zip'; 60 | zips(ind).folder = 'MFX 65434'; 61 | zips(ind).test = 'DTQP_solve'; 62 | 63 | % obtain full function path 64 | full_fun_path = which(mfilename('fullpath')); 65 | outputdir = fullfile(fileparts(full_fun_path),'include'); 66 | 67 | % download and unzip 68 | DownloadWebZips(zips,outputdir) 69 | 70 | disp(' ') 71 | end 72 | %-------------------------------------------------------------------------- 73 | function AddSubmissionContents(name) 74 | disp('--- Adding submission contents to path') 75 | disp(' ') 76 | 77 | % current file 78 | fullfuncdir = which(name); 79 | 80 | % current folder 81 | submissiondir = fullfile(fileparts(fullfuncdir)); 82 | 83 | % add folders and subfolders to path 84 | addpath(genpath(submissiondir)) 85 | end 86 | %-------------------------------------------------------------------------- 87 | function DownloadWebZips(zips,outputdir) 88 | 89 | % store the current directory 90 | olddir = pwd; 91 | 92 | % create a folder for outputdir 93 | if ~exist(outputdir, 'dir') 94 | mkdir(outputdir); % create the folder 95 | else 96 | addpath(genpath(outputdir)); % add folders and subfolders to path 97 | end 98 | 99 | % change to the output directory 100 | cd(outputdir) 101 | 102 | % go through each zip 103 | for k = 1:length(zips) 104 | 105 | % get data 106 | url = zips(k).url; 107 | folder = zips(k).folder; 108 | test = zips(k).test; 109 | 110 | % first check if the test file is in the path 111 | if exist(test,'file') == 0 112 | 113 | try 114 | % download zip file 115 | zipname = websave(folder,url); 116 | 117 | % save location 118 | outputdirname = fullfile(outputdir,folder); 119 | 120 | % create a folder utilizing name as the foldername name 121 | if ~exist(outputdirname, 'dir') 122 | mkdir(outputdirname); 123 | end 124 | 125 | % unzip the zip 126 | unzip(zipname,outputdirname); 127 | 128 | % delete the zip file 129 | delete([folder,'.zip']) 130 | 131 | % output to the command window 132 | disp(['Downloaded and unzipped ',folder]) 133 | 134 | catch % failed to download 135 | % output to the command window 136 | disp(['Failed to download ',folder]) 137 | 138 | % remove the html file 139 | delete([folder,'.html']) 140 | 141 | end 142 | 143 | else 144 | % output to the command window 145 | disp(['Already available ',folder]) 146 | end 147 | end 148 | 149 | % change back to the original directory 150 | cd(olddir) 151 | end 152 | %-------------------------------------------------------------------------- 153 | function OpenThisFile(name) 154 | disp(['--- Opening ', name]) 155 | 156 | try 157 | % open the file 158 | open(name); 159 | catch % error 160 | disp(['Could not open ', name]) 161 | end 162 | 163 | disp(' ') 164 | end 165 | %-------------------------------------------------------------------------- 166 | function CloseThisFile(name) 167 | disp(['--- Closing ', name]) 168 | disp(' ') 169 | 170 | % get editor information 171 | h = matlab.desktop.editor.getAll; 172 | 173 | % go through all open files in the editor 174 | for k = 1:numel(h) 175 | % check if this is the file 176 | if ~isempty(strfind(h(k).Filename,name)) 177 | % close this file 178 | h(k).close 179 | end 180 | end 181 | end -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016, Daniel Herber 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## README (optimal-control-direct-method-examples) 2 | 3 | [![GitHub release](https://img.shields.io/github/release/danielrherber/optimal-control-direct-method-examples.svg)](https://github.com/danielrherber/optimal-control-direct-method-examples/releases/latest) 4 | [![license](https://img.shields.io/github/license/danielrherber/optimal-control-direct-method-examples.svg)](https://github.com/danielrherber/optimal-control-direct-method-examples/blob/master/License) 5 | 6 | [![](https://img.shields.io/badge/language-matlab-EF963C.svg)](https://www.mathworks.com/products/matlab.html) 7 | [![](https://img.shields.io/github/issues-raw/danielrherber/optimal-control-direct-method-examples.svg)](https://github.com/danielrherber/optimal-control-direct-method-examples/issues) 8 | [![GitHub contributors](https://img.shields.io/github/contributors/danielrherber/optimal-control-direct-method-examples.svg)](https://github.com/danielrherber/optimal-control-direct-method-examples/graphs/contributors) 9 | [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/optimal-control-direct-method-examples/community) 10 | 11 | Teaching examples for three direct methods for solving optimal control problems, namely [single shooting](src/Method_SingleShooting.m), [single step](src/Method_SingleStep.m), and [pseudospectral](src/Method_Pseudospectral.m). 12 | 13 | ![readme_image.svg](optional/readme_image.svg) 14 | 15 | --- 16 | ### Install 17 | - Download the [project files](https://github.com/danielrherber/optimal-control-direct-method-examples/archive/master.zip) 18 | - Run [INSTALL_Direct_Method_Examples.m](INSTALL_Direct_Method_Examples.m) in the MATLAB Command Window *(automatically adds project files to your MATLAB path, downloads the required files, and opens an example)* 19 | ```matlab 20 | INSTALL_Direct_Method_Examples 21 | ``` 22 | - See [Run_All_Examples.m](src/Run_All_Examples.m) to run all the examples or the individual examples in `/src` 23 | ```matlab 24 | Run_All_Examples 25 | ``` 26 | 27 | ### External Includes 28 | See [INSTALL_Direct_Method_Examples.m](INSTALL_Direct_Method_Examples.m) for more information 29 | - **MATLAB File Exchange Submission IDs** (51104, 65434) 30 | 31 | ### MATLAB Version 32 | The main methods should work on version R2014b or newer. 33 | [Method_DTQPProject.m](optional/Method_DTQPProject.m) requires version R2016a or newer. 34 | Some of the plot decorations require newer versions that support structure properties in figures. 35 | The [Optimization Toolbox](https://www.mathworks.com/products/optimization.html) is required. 36 | 37 | --- 38 | ### Bryson-Denham Problem 39 | 40 | This is the optimal control problem used in the examples. The problem formulation is: 41 | 42 | ![bd_formulation.svg](src/bryson-denham/BrysonDenham_formulation.svg) 43 | 44 | The optimal control solution when `\ell` is between 0 and 1/6 is: 45 | 46 | ![bd_solution.svg](src/bryson-denham/BrysonDenham_solution.svg) 47 | 48 | Please see the following files that calculate the optimal [states](src/bryson-denham/BrysonDenham_Solution_States.m) and [control](src/bryson-denham/BrysonDenham_Solution_Control.m). See pages 120–123 of *A. E. Bryson and Y.-C. Ho, Applied Optimal Control, revised printing ed. Taylor & Francis, 1975* for more details on this problem. 49 | 50 | --- 51 | ### General Information 52 | 53 | #### Contributors 54 | - [Daniel R. Herber](https://github.com/danielrherber) 55 | 56 | #### Project Links 57 | - [https://github.com/danielrherber/optimal-control-direct-method-examples](https://github.com/danielrherber/optimal-control-direct-method-examples) 58 | - [http://www.mathworks.com/matlabcentral/fileexchange/62546](http://www.mathworks.com/matlabcentral/fileexchange/62546) -------------------------------------------------------------------------------- /include/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | */ 3 | !.gitignore -------------------------------------------------------------------------------- /optional/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | _private/ -------------------------------------------------------------------------------- /optional/Method_DTQPProject.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Method_DTQPProject.m 3 | % Attempt to solve the Bryson-Denham problem using the methods in the DT QP 4 | % Project (solves linear-quadratic dynamic optimization (LQDO) problems 5 | % using direct transcription (DT) and quadratic programming (QP)) 6 | % Link: https://github.com/danielrherber/dt-qp-project 7 | %-------------------------------------------------------------------------- 8 | % 9 | %-------------------------------------------------------------------------- 10 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 11 | % Illinois at Urbana-Champaign 12 | % https://github.com/danielrherber/optimal-control-direct-method-examples 13 | %-------------------------------------------------------------------------- 14 | function Method_DTQPProject 15 | % problem parameters 16 | p.y10 = 0; p.y1f = 0; p.y20 = 1; p.y2f = -1; % boundary conditions 17 | p.l = 1/9; 18 | % direct transcription parameters 19 | opts.dt.nt = 10; % number of node points 20 | method = 1; 21 | switch method 22 | case 1 % similar to Method_SingleStep.m 23 | opts.dt.mesh = 'ED'; % time grid method 24 | opts.dt.defects = 'TR'; % defect constraint method 25 | opts.dt.quadrature = 'CTR'; % quadrature method 26 | case 2 % similar to Method_Pseudospectral.m 27 | opts.dt.mesh = 'LGL'; % time grid method 28 | opts.dt.defects = 'PS'; % defect constraint method 29 | opts.dt.quadrature = 'G'; % quadrature method 30 | end 31 | % time horizon 32 | setup.t0 = 0; setup.tf = 1; % time horizon 33 | % system dynamics 34 | A = [0 1;0 0]; B = [0;1]; 35 | % Lagrange term 36 | L(1).left = 1; L(1).right = 1; L(1).matrix = 1/2; % 1/2*u^2 37 | % simple bounds 38 | UB(1).right = 4; UB(1).matrix = [p.y10;p.y20]; % initial states 39 | LB(1).right = 4; LB(1).matrix = [p.y10;p.y20]; 40 | UB(2).right = 5; UB(2).matrix = [p.y1f;p.y2f]; % final states 41 | LB(2).right = 5; LB(2).matrix = [p.y1f;p.y2f]; 42 | UB(3).right = 2; UB(3).matrix = [p.l;Inf]; % states 43 | % combine structures 44 | setup.A = A; setup.B = B; setup.L = L; setup.UB = UB; setup.LB = LB; setup.p = p; 45 | % solve the problem 46 | [~,U,Y,~,~,p,~] = DTQP_solve(setup,opts); 47 | % plots 48 | p.l = p.p.l; 49 | Plots(Y(:,1),Y(:,2),U,p,'DT QP Project') 50 | end -------------------------------------------------------------------------------- /optional/readme_image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /src/Method_Pseudospectral.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Method_Pseudospectral.m 3 | % Attempt to solve the Bryson-Denham problem using a pseudospectral method 4 | % (namely LGL nodes and Gaussian quadrature) 5 | %-------------------------------------------------------------------------- 6 | % 7 | %-------------------------------------------------------------------------- 8 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 9 | % Illinois at Urbana-Champaign 10 | % https://github.com/danielrherber/optimal-control-direct-method-examples 11 | %-------------------------------------------------------------------------- 12 | function Method_Pseudospectral 13 | % problem parameters 14 | p.ns = 2; p.nu = 1; % number of states and controls 15 | p.t0 = 0; p.tf = 1; % time horizon 16 | p.y10 = 0; p.y1f = 0; p.y20 = 1; p.y2f = -1; % boundary conditions 17 | p.l = 1/9; 18 | % direct transcription parameters 19 | p.nt = 10; % number of node points 20 | % p.nt = 50; % number of node points 21 | p.tau = LGL_nodes(p.nt-1); % scaled time horizon 22 | p.D = LGL_Dmatrix(p.tau); % for defect constraints 23 | p.w = LGL_weights(p.tau); % for gaussian quadrature 24 | % discretized variable indices in x = [y1,y2,u]; 25 | p.y1i = 1:p.nt; p.y2i = p.nt+1:2*p.nt; p.ui = 2*p.nt+1:3*p.nt; 26 | x0 = zeros(p.nt*(p.ns+p.nu),1); % initial guess (all zeros) 27 | options = optimoptions(@fmincon,'display','iter','MaxFunEvals',1e5); % options 28 | % solve the problem 29 | x = fmincon(@(x) objective(x,p),x0,[],[],[],[],[],[],@(x) constraints(x,p),options); 30 | % obtain the optimal solution 31 | y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract 32 | p.t = (p.tau*(p.tf-p.t0) + (p.tf+p.t0))/2; % unscale time horizon 33 | % plots 34 | Plots(y1,y2,u,p,'Pseudospectral') 35 | end 36 | % objective function 37 | function f = objective(x,p) 38 | u = x(p.ui); % extract 39 | L = u.^2; % integrand 40 | f = (p.tf-p.t0)/2*dot(p.w,L)/2; % calculate objective 41 | end 42 | % constraint function 43 | function [c,ceq] = constraints(x,p) 44 | y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract 45 | Y = [y1,y2]; F = (p.tf-p.t0)/2*[y2,u]; % create matrices (p.nt x p.ns) 46 | ceq1 = y1(1) - p.y10; % initial state conditions 47 | ceq2 = y2(1) - p.y20; 48 | ceq3 = y1(end) - p.y1f; % final state conditions 49 | ceq4 = y2(end) - p.y2f; 50 | ceq5 = p.D*Y - F; % defect constraints matrix form (pseudospectral) 51 | c1 = y1 - p.l; % path constraints 52 | c = c1; ceq = [ceq1;ceq2;ceq3;ceq4;ceq5(:)]; % combine constraints 53 | end -------------------------------------------------------------------------------- /src/Method_SingleShooting.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Method_SingleShooting.m 3 | % Attempt to solve the Bryson-Denham problem using a single shooting method 4 | %-------------------------------------------------------------------------- 5 | % 6 | %-------------------------------------------------------------------------- 7 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 8 | % Illinois at Urbana-Champaign 9 | % https://github.com/danielrherber/optimal-control-direct-method-examples 10 | %-------------------------------------------------------------------------- 11 | function Method_SingleShooting 12 | % problem parameters 13 | p.ns = 2; p.nu = 1; % number of states and controls 14 | p.t0 = 0; p.tf = 1; % time horizon 15 | p.y10 = 0; p.y1f = 0; p.y20 = 1; p.y2f = -1; % boundary conditions 16 | p.l = 1/9; 17 | % shooting parameters 18 | p.nt = 10; % number of node points 19 | % p.nt = 50; % number of node points 20 | p.t = linspace(p.t0,p.tf,p.nt)'; % time horizon 21 | % discretized variable indices in x = [u]; 22 | p.ui = 1:p.nt; 23 | x0 = zeros(p.nt*(p.nu),1); % initial guess (all zeros) 24 | options = optimoptions(@fmincon,'display','iter','MaxFunEvals',5e3); % option 25 | % solve the problem 26 | x = fmincon(@(x) objective(x,p),x0,[],[],[],[],[],[],@(x) constraints(x,p),options); 27 | % obtain the optimal solution 28 | p.u = x(p.ui); % extract 29 | [~,Y] = ode45(@(t,y) derivative(t,y,p),p.t,[p.y10,p.y20]); % simulation 30 | y1 = Y(:,1); y2 = Y(:,2); % extract states 31 | % plots 32 | Plots(y1,y2,p.u,p,'Single Shooting') 33 | end 34 | % objective function 35 | function f = objective(x,p) 36 | u = x(p.ui); % extract 37 | L = u.^2/2; % integrand 38 | f = trapz(p.t,L); % calculate objective 39 | end 40 | % constraint function 41 | function [c,ceq] = constraints(x,p) 42 | p.u = x(p.ui); % extract 43 | [~,Y] = ode45(@(t,y) derivative(t,y,p),p.t,[p.y10,p.y20]); % simulation 44 | y1 = Y(:,1); y2 = Y(:,2); % extract states 45 | ceq1 = y1(end) - p.y1f; % final state conditions 46 | ceq2 = y2(end) - p.y2f; 47 | c1 = y1 - p.l; % path constraints 48 | % combine constraints 49 | c = c1; ceq = [ceq1;ceq2]; 50 | end 51 | % derivative function 52 | function dydt = derivative(t,y,p) 53 | dydt(1,1) = y(2); % v 54 | dydt(2,1) = interp1(p.t,p.u,t); % u 55 | end -------------------------------------------------------------------------------- /src/Method_SingleStep.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Method_SingleStep.m 3 | % Attempt to solve the Bryson-Denham problem using a single-step method 4 | % (namely the trapezodial rule with composite trapezoidal quadrature) 5 | %-------------------------------------------------------------------------- 6 | % 7 | %-------------------------------------------------------------------------- 8 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 9 | % Illinois at Urbana-Champaign 10 | % https://github.com/danielrherber/optimal-control-direct-method-examples 11 | %-------------------------------------------------------------------------- 12 | function Method_SingleStep 13 | % problem parameters 14 | p.ns = 2; p.nu = 1; % number of states and controls 15 | p.t0 = 0; p.tf = 1; % time horizon 16 | p.y10 = 0; p.y1f = 0; p.y20 = 1; p.y2f = -1; % boundary conditions 17 | p.l = 1/9; 18 | % direct transcription parameters 19 | p.nt = 10; % number of node points 20 | % p.nt = 50; % number of node points 21 | p.t = linspace(p.t0,p.tf,p.nt)'; % time horizon 22 | p.h = diff(p.t); % step size 23 | % discretized variable indices in x = [y1,y2,u]; 24 | p.y1i = 1:p.nt; p.y2i = p.nt+1:2*p.nt; p.ui = 2*p.nt+1:3*p.nt; 25 | x0 = zeros(p.nt*(p.ns+p.nu),1); % initial guess (all zeros) 26 | options = optimoptions(@fmincon,'display','iter','MaxFunEvals',1e5); % options 27 | % solve the problem 28 | x = fmincon(@(x) objective(x,p),x0,[],[],[],[],[],[],@(x) constraints(x,p),options); 29 | % obtain the optimal solution 30 | y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract 31 | % plots 32 | Plots(y1,y2,u,p,'Single Step') 33 | end 34 | % objective function 35 | function f = objective(x,p) 36 | u = x(p.ui); % extract 37 | L = u.^2/2; % integrand 38 | f = trapz(p.t,L); % calculate objective 39 | end 40 | % constraint function 41 | function [c,ceq] = constraints(x,p) 42 | y1 = x(p.y1i); y2 = x(p.y2i); u = x(p.ui); % extract 43 | Y = [y1,y2]; F = [y2,u]; % create matrices (p.nt x p.ns) 44 | ceq1 = y1(1) - p.y10; % initial state conditions 45 | ceq2 = y2(1) - p.y20; 46 | ceq3 = y1(end) - p.y1f; % final state conditions 47 | ceq4 = y2(end) - p.y2f; 48 | % defect constraints 49 | 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) ); 50 | 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) ); 51 | c1 = y1 - p.l; % path constraints 52 | c = c1; ceq = [ceq1;ceq2;ceq3;ceq4;ceq5;ceq6]; % combine constraints 53 | end -------------------------------------------------------------------------------- /src/Plots.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Method_Pseudospectral.m 3 | % Plotting function 4 | %-------------------------------------------------------------------------- 5 | % 6 | %-------------------------------------------------------------------------- 7 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 8 | % Illinois at Urbana-Champaign 9 | % https://github.com/danielrherber/optimal-control-direct-method-examples 10 | %-------------------------------------------------------------------------- 11 | function Plots(y,v,u,p,method) 12 | %---------------------------------------------------------------------- 13 | fontlabel = 20; % x,y label font size 14 | fontlegend = 12; % x,y legend font size 15 | fonttick = 12; % x,y rick font size 16 | wcolor = [1 1 1]; % white color 17 | bcolor = [0 0 0]; % black color 18 | mycolor = lines(8); 19 | 20 | set(0,'DefaultTextInterpreter','latex'); % change the text interpreter 21 | set(0,'DefaultLegendInterpreter','latex'); % change the legend interpreter 22 | set(0,'DefaultAxesTickLabelInterpreter','latex'); % change the tick interpreter 23 | 24 | T = linspace(p.t0,p.tf,10000); 25 | 26 | if strcmp(method,'Pseudospectral') 27 | yl = LagrangeInter(p.t',y',T); 28 | vl = LagrangeInter(p.t',v',T); 29 | ul = LagrangeInter(p.t',u',T); 30 | end 31 | 32 | %---------------------------------------------------------------------- 33 | % plot states 34 | hf = figure; % create a new figure and save handle 35 | hf.Color = wcolor; % change the figure background color 36 | 37 | Xopt = BrysonDenham_Solution_States(T,p.l); 38 | plot(T,Xopt(:,1),'-','linewidth',2,'color',mycolor(6,:)); hold on 39 | plot(T,Xopt(:,2),'-','linewidth',2,'color',mycolor(2,:)); hold on 40 | 41 | plot(p.t,y,'.','markersize',14,'color',mycolor(1,:)); hold on 42 | plot(p.t,v,'.','markersize',14,'color',mycolor(7,:)); hold on 43 | 44 | if strcmp(method,'Pseudospectral') 45 | plot(T,yl,'-','color',mycolor(1,:)); hold on 46 | plot(T,vl,'-','color',mycolor(7,:)); hold on 47 | end 48 | 49 | mytitle = [method,' Method - States']; % title with latex 50 | myxlabel = '$t$'; % x label with latex 51 | myylabel = 'states'; % y label with latex 52 | mylegend = {'True Solution - State 1','True Solution - State 2',... 53 | [method, ' - State 1'],[method, ' - State 2']}; % legend with latex 54 | xlabel(myxlabel) % create x label 55 | ylabel(myylabel) % create y label 56 | ha = gca; % get current axis handle 57 | try 58 | ha.XAxis.Color = bcolor; % change the x axis color to black (not a dark grey) 59 | ha.XAxis.FontSize = fonttick; % change x tick font size 60 | ha.YAxis.FontSize = fonttick; % change y tick font size 61 | ha.XAxis.Label.FontSize = fontlabel; % change x label font size 62 | ha.YAxis.Label.FontSize = fontlabel; % change y label font size 63 | ht = title(mytitle); 64 | ht.FontSize = fontlabel; 65 | hl = legend(mylegend,'location','Best'); % create legend 66 | hl.FontSize = fontlegend; % change legend font size 67 | hl.EdgeColor = bcolor; % change the legend border to black (not a dark grey) 68 | catch 69 | disp('plot formatting failed (try using a version that supports HG2)') 70 | end 71 | 72 | %---------------------------------------------------------------------- 73 | % plots control 74 | hf = figure; % create a new figure and save handle 75 | hf.Color = wcolor; % change the figure background color 76 | 77 | Uopt = BrysonDenham_Solution_Control(T,p.l); 78 | plot(T,Uopt(:,1),'linewidth',1,'color',mycolor(6,:)); hold on 79 | 80 | plot(p.t,u,'.','markersize',14,'color',mycolor(1,:)); hold on 81 | 82 | if strcmp(method,'Pseudospectral') 83 | plot(T,ul,'-','color',mycolor(1,:)); hold on 84 | end 85 | 86 | mytitle = [method,' Method - Control']; % title with latex 87 | myxlabel = '$t$'; % x label with latex 88 | myylabel = 'control'; % y label with latex 89 | mylegend = {'True Solution - Control',[method, ' - Control']}; % legend with latex 90 | xlabel(myxlabel) % create x label 91 | ylabel(myylabel) % create y label 92 | try 93 | ha = gca; % get current axis handle 94 | ha.XAxis.Color = bcolor; % change the x axis color to black (not a dark grey) 95 | ha.XAxis.FontSize = fonttick; % change x tick font size 96 | ha.YAxis.FontSize = fonttick; % change y tick font size 97 | ha.XAxis.Label.FontSize = fontlabel; % change x label font size 98 | ha.YAxis.Label.FontSize = fontlabel; % change y label font size 99 | ht = title(mytitle); 100 | ht.FontSize = fontlabel; 101 | hl = legend(mylegend,'location','Best'); % create legend 102 | hl.FontSize = fontlegend; % change legend font size 103 | hl.EdgeColor = bcolor; % change the legend border to black (not a dark grey) 104 | catch 105 | disp('plot formatting failed (try using a version that supports HG2)') 106 | end 107 | end -------------------------------------------------------------------------------- /src/Run_All_Examples.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Run_All_Examples.m 3 | % This script will run each method 4 | %-------------------------------------------------------------------------- 5 | % 6 | %-------------------------------------------------------------------------- 7 | % Primary Contributor: Daniel R. Herber, Graduate Student, University of 8 | % Illinois at Urbana-Champaign 9 | % https://github.com/danielrherber/optimal-control-direct-method-examples 10 | %-------------------------------------------------------------------------- 11 | close all 12 | 13 | Method_SingleShooting 14 | 15 | Method_SingleStep 16 | 17 | Method_Pseudospectral 18 | 19 | % Method_DTQPProject -------------------------------------------------------------------------------- /src/bryson-denham/BrysonDenham_Solution_Control.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrherber/optimal-control-direct-method-examples/1d996c95605275798982591d47c6bd1578019081/src/bryson-denham/BrysonDenham_Solution_Control.m -------------------------------------------------------------------------------- /src/bryson-denham/BrysonDenham_Solution_States.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrherber/optimal-control-direct-method-examples/1d996c95605275798982591d47c6bd1578019081/src/bryson-denham/BrysonDenham_Solution_States.m -------------------------------------------------------------------------------- /src/bryson-denham/BrysonDenham_solution.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | --------------------------------------------------------------------------------