{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"active-ipynb",
"remove-input",
"remove-output"
]
},
"outputs": [],
"source": [
"# This cell is mandatory in all Dymos documentation notebooks.\n",
"missing_packages = []\n",
"try:\n",
" import openmdao.api as om # noqa: F401\n",
"except ImportError:\n",
" if 'google.colab' in str(get_ipython()):\n",
" !python -m pip install openmdao[notebooks]\n",
" else:\n",
" missing_packages.append('openmdao')\n",
"try:\n",
" import dymos as dm # noqa: F401\n",
"except ImportError:\n",
" if 'google.colab' in str(get_ipython()):\n",
" !python -m pip install dymos\n",
" else:\n",
" missing_packages.append('dymos')\n",
"try:\n",
" import pyoptsparse # noqa: F401\n",
"except ImportError:\n",
" if 'google.colab' in str(get_ipython()):\n",
" !pip install -q condacolab\n",
" import condacolab\n",
" condacolab.install_miniconda()\n",
" !conda install -c conda-forge pyoptsparse\n",
" else:\n",
" missing_packages.append('pyoptsparse')\n",
"if missing_packages:\n",
" raise EnvironmentError('This notebook requires the following packages '\n",
" 'please install them and restart this notebook\\'s runtime: {\",\".join(missing_packages)}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(getting_started:collocation:what_is_collocation)=\n",
"# What is collocation?\n",
"\n",
"Dymos is focused on direct optimization methods based on an implicit integration technique, collocation.\n",
"\n",
"The _state_ of a dynamic system defines its configuration at a point in time.\n",
"Common state variables for dynamic systems are position, velocity, and mass.\n",
"Given an initial state, a time duration, and ordinary differential equations that define the evolution of the states in time, the state of the system at the end of the time duration can be determined.\n",
"This is known as the _initial value problem_ (IVP) and there are numerous techniques and software packages that can be used to solve the IVP.\n",
"The initial value problem is typically the basis for the simulation of systems.\n",
"This time-marching approach is the basis for _shooting methods_ in optimization.\n",
"While Dymos supports shooting methods, its focus is on implicit collocation techniques, for performance reasons.\n",
"\n",
"First, a few assumptions about the dynamic system:\n",
"\n",
"1. Over portions of the trajectory, the state is continuous (there are no instantaneous changes in the states)\n",
"2. Over portions of the trajectory, the state is continuous in its first derivative w.r.t. time. (there are no instantaneous changes in the state rates)\n",
"\n",
"If those two conditions are met, then it's reasonable to fit a polynomial to a plot of the state value over time.\n",
"Given the initial or final value of a state, and values of its rate at some number of points across the trajectory, then a polynomial can be fit whose initial or final value matches, and whose rates match the sampled rates.\n",
"The value of the state at any point throughout the trajectory can then be inferred by interpolating the collocated polynomial.\n",
"\n",
"Solving this trajectory implicitly basically means _guessing_ values for the states along the trajectory.\n",
"While one could use a power series polynomial coefficients ($a t^2 + b t + c$), these coefficients can have vastly different values depending on the shape of the curve, making them difficult to scale numerically.\n",
"Instead, Lagrange interpolating polynomials are typically used, where the actual values to be interpolated at various points are the implicit variables.\n",
"This makes scaling the problem easier, and gives the implicit variables more intuitive meaning, making it easier to provide an initial guess.\n",
"\n",
"## Example: Simulating the fall of an object\n",
"\n",
"As a \"hello, world\" problem for Dymos, consider the vertical fall of an object acting under gravity - like Galileo dropping cannonballs from the Tower of Pisa.\n",
"Ignoring aerodynamics and treating the ball as a point mass in a rectilinear gravity field, the motion is governed by:\n",
"\n",
"\\begin{align}\n",
" \\ddot{y} = -g\n",
"\\end{align}\n",
"\n",
"The techniques in Dymos are generally centered around first-order dynamics, so we convert the above equation into the following system of ODEs.\n",
"\n",
"\\begin{align}\n",
" \\dot{y} &= v_y \\\\\n",
" \\dot{v_y} &= -g\n",
"\\end{align}\n",
"\n",
"One common way to propagate this trajectory would be to use an \"explicit time-marching\" approach.\n",
"That is, we can use Euler's method or a Runge-Kutta approach to propagate the trajectory of the ball, one small slice of time at a time.\n",
"When performing trajectory optimization, the trajectory is typically evaluated at least dozens of times.\n",
"If the ODE for the system is computationally expensive, this time-marching approach can take a very long time.\n",
"\n",
"Instead, we can use an implicit simulation technique to more efficiently model the trajectory.\n",
"First, let's assume that the value of the _states_ $y$ and $v_y$ smoothly vary in time (there's no teleportation or instantaneous changes in velocity).\n",
"Now we can fit a polynomial to the plot of each of these states with respect to time.\n",
"In this case, basic physics tells us that $v_y$ should be linear with time and $y$ should be quadratic with time.\n",
"\n",
"Now for the simulation, lets solve a _boundary value problem_.\n",
"We know the initial and final height of the ball.\n",
"We know the initial velocity but not the terminal velocity.\n",
"\n",
"_How long does it take the ball to reach the ground from an initial height of 100 m?_\n",
"\n",
"We will explain how this problem is solved using the three implicit simulation techniques in Dymos: high-order Gauss-Lobatto collocation, the Radau Pseudospectral Method, and the Birkhoff Pseudospectral Method.\n",
"\n",
"## Finding the trajectory using high-order Legendre-Gauss-Lobatto collocation\n",
"\n",
"Using a 3rd-order polynomial segment to mimic the trajectory, we have two states and thus two polynomials.\n",
"Legendre-Gauss-Lobatto (LGL) collocation uses knowledge of the states and state-rates to form an interpolating polynomial.\n",
"A third-order polynomial requires four pieces of information to define it.\n",
"We'll take two points along the trajectory, and use those to guess the state values.\n",
"In Dymos, these points where state values are provided are called the _state discretization nodes_.\n",
"In LGL collocation, these points are chosen to be the LGL _nodes_ in the dimensionless time of the segment, which we call $\\tau_s$.\n",
"\n",
"Our initial guess for the trajectory might look something like this:\n",
"\n",
"| Variables | Description | Value | Notes |\n",
"|------------|-------------------|----------------|------------------------|\n",
"| $y_0$ | initial height | 100 m | fixed |\n",
"| $y_f$ | final height | 0 m | fixed |\n",
"| $v_{y0}$ | initial velocity | 0 m/s | fixed |\n",
"| $v_{yf}$ | final velocity | -50 m/s | free |\n",
"| $t_0$ | initial time | 0 | fixed |\n",
"| $t_d$ | time duration | 5 | free |\n",
"| $g$ | grav. acceleration| 9.80665 m/s^2 | assumed |\n",
"\n",
"To form 3rd-order polynomials for the states we need four pieces of information, but so far we only have the two endpoint values.\n",
"We'll use the state rates at the state discretization nodes to provide the other two values needed for interpolation.\n",
"To obtain these, we evaluate our ODE at the state discretization nodes.\n",
"\n",
"\\begin{align}\n",
" \\dot{y}_0 &= 0 \\\\\n",
" \\dot{y}_f &= -50 \\\\\n",
" \\dot{v}_{y0} &= -9.80665 \\\\\n",
" \\dot{v}_{yf} &= -9.80665\n",
"\\end{align}\n",
"\n",
"![Screenshot](scripts/lgl_animation_1.png)\n",
"\n",
"But how do we know that our assumed trajectory is correct?\n",
"In LGL collocation, we check the interpolated slope of the polynomial at a 3rd point (the collocation node) and compare it to an evaluation of the ODE at the same point.\n",
"If the difference between the two is sufficiently close to zero, we can be somewhat confident that our polynomial is a reasonable match for the true time-history.\n",
"We call this difference in slope the collocation _defect_.\n",
"\n",
"Having computed the ODE at the state discretization nodes, we can form interpolants for the values and the slope of the states at the collocation nodes.\n",
"Dymos uses Lagrange interpolants, such that the inputs to the system are the values of the states and controls, rather than less intuitive coefficients.\n",
"In this case, the state values at our single collocation node are:\n",
"\n",
"\\begin{align}\n",
" y_m &= 50 \\\\\n",
" v_{ym} &= -25\n",
"\\end{align}\n",
"\n",
"![Screenshot](scripts/lgl_animation_2.png)\n",
"\n",
"The polynomial slopes at the collocation node are:\n",
"\n",
"\\begin{align}\n",
" y'_m &= 50 \\\\\n",
" v'_{ym} &= -25\n",
"\\end{align}\n",
"\n",
"Now, having the state and time values at the collocation nodes, we can again evaluate the ODE.\n",
"\n",
"\\begin{align}\n",
" \\dot{y}_m &= -17 \\\\\n",
" \\dot{v}_{ym} &= -9.80665\n",
"\\end{align}\n",
"\n",
"![Screenshot](scripts/lgl_animation_3.png)\n",
"\n",
"In this case the known variables are the value of the polynomial at the left endpoint ($y_0$), and the value of the independent variable at the left and right endpoints of the interval to be fitted ($x_0$, $x_1$)\n",
"In this case, there are no _control_ inputs to the ODE.\n",
"However, if there were, the value of the control would also need to be provided at the collocation node.\n",
"Thus, in high-order Gauss-Lobatto collocation, the _control input nodes_ include both the state discretization nodes and the collocation nodes.\n",
"\n",
"The free variables in the problem ($t_{duration}$ and $vy_f$) can be iterated until the difference between the interpolated state rates and the ODE-computed state rates is zero.\n",
"\n",
"![Screenshot](scripts/lgl_solution_5.png)\n",
"\n",
"## Finding the trajectory using the Radau Pseudospectral Method\n",
"\n",
"Again, there are two states, and two corresponding 3rd-order polynomials representing the time history.\n",
"As with the Gauss-Lobatto method, a third-order polynomial requires four pieces of information to define it.\n",
"In the case of the Radau Pseudospectral Method, we'll use four state values, guessed at the Radau nodes in dimensionless time in addition to the right endpoint of the interval (the _state discretization nodes_).\n",
"\n",
"A linear interpolation of the endpoint values will serve as the initial guess in this instance.\n",
"The three Radau nodes that don't include the right endpoint will serve as the _collocation nodes_ in this case.\n",
"Since these are a subset of the state discretization nodes, no interpolation of values is necessary...all of the state values have been provided.\n",
"\n",
"![Screenshot](scripts/lgr_animation_0.png)\n",
"\n",
"The derivative of the interpolating polynomial is computed using a differentiation matrix and the state discretization values.\n",
"\n",
"![Screenshot](scripts/lgr_animation_2.png)\n",
"\n",
"Now the ODE can be evaluated to calculate the state rates, and the results compared to the interpolated slopes.\n",
"\n",
"![Screenshot](scripts/lgr_animation_3.png)\n",
"\n",
"Again, the free variables are iterated until the defects are zero and any boundary conditions are met.\n",
"\n",
"![Screenshot](scripts/lgr_solution_5.png)\n",
"\n",
"## Finding the trajectory using the Birkhoff Pseudospectral Method\n",
"\n",
"As before, there are two states and two 3rd-order polynomials representing the time history of each states.\n",
"In the Birkhoff pseudospectral method, all states and state rates are used as free variables.\n",
"Additionally, the initial and final nodes are represented independently and may also be free variables depending on the problem.\n",
"So each state eight pieces of information to be fully solved.\n",
"In this problem, the initial and final points of the position and the initial point of the velocity are fixed.\n",
"The final velocity is left open to be determined by the terminal boundary constraint.\n",
"\n",
"![Screenshot](scripts/birkhoff_animation_1.png)\n",
"\n",
"The state variables constrained such that the end points are equal to the initial and final nodes.\n",
"For illustrative purposes, the state variables are initialized as the average of the guess for initial and final states.\n",
"\n",
"![Screenshot](scripts/birkhoff_animation_2.png)\n",
"\n",
"We can use the initial state value, the state rates, and an integration matrix to compute the state value at each subsequent node.\n",
"These values can be compared to obtain the two state defects.\n",
"\n",
"![Screenshot](scripts/birkhoff_animation_3.png)\n",
"\n",
"The state values can be used to evaluate the ODE.\n",
"The state rates computed from the ODE can be compared against the state rate free variables to obtain the three state rate defects.\n",
"\n",
"![Screenshot](scripts/birkhoff_animation_4.png)\n",
"\n",
"\n",
"The free variables are iterated until the defects are zero and the boundary constraints are satisfied.\n",
"\n",
"![Screenshot](scripts/birkhoff_animation_5.png)\n",
"\n",
"\n",
"## Multiple Segments\n",
"\n",
"The simple examples above use one single 3rd-order polynomial to represent the time history of the states.\n",
"With more complex states, a single 3rd-order polynomial would not be capable of replicating the time history.\n",
"In practice, we can use more polynomial segments _and_ higher-order polynomials to better match the dynamics for the Gauss-Lobatto and Radau Pseudospectral methods.\n",
"For the Birkhoff pseudospectral method we only use one segment but use higher-order polynomials.\n",
"\n",
"In the case of adding more segments, one can choose whether the segment boundaries are shared by the segments, or independent.\n",
"If they are shared, fewer design variables are necessary, but it may be more difficult for the optimizer to search for a solution.\n",
"This is called \"compressed\" transcription.\n",
"On the other hand, we can doubly-specify state values at segment boundaries as design variables, thus increasing the size of the problem.\n",
"In this \"uncompressed\" formulation, continuity constraints are imposed at the segment bounds to ensure that there are no discontinuities in the state time-history at segment bounds.\n",
"\n",
"## LGL vs LGR Collocation\n",
"\n",
"Gauss-Lobatto collocation results in smaller NLP sizes for the optimizer since fewer states are treated as design variables.\n",
"The cost of this reduction is the interpolation step in the Gauss-Lobatto algorithm.\n",
"While the Radau Pseudospectral method requires one evaluation of the ODE to assess the defects, the Gauss-Lobatto method requires two.\n",
"In addition, the interpolation step used by the Gauss-Lobatto method can result in interpolated state values falling well outside the user's expected range if the initial guess is not sufficiently accurate.\n",
"This can cause convergence issues if there are nonlinear solvers within the ODE that rely on a reasonable guess to achieve convergence.\n",
"\n",
"## Birkhoff Pseudospectral Method vs LGL and LGR Collocation\n",
"\n",
"There are two notable differences between the birkhoff pseudospectral method and the two other methods.\n",
"Firstly, the collocation constraints are applied in _integral_ form rather than _differential_ form.\n",
"Secondly, an additional layer of slack is introduced to the NLP by introducing _virtual variables_ as stand-ins for the state rates.\n",
"These virtual variables are constrained to equal the state rate obtained by evaluating the ODE and are used to compute state values and apply the state defects.\n",
"These two factors combine to produce an NLP that is better conditioned and whose solution is more equivalent to the solution of the original optimal control problem.\n",
"The improved conditioning allows for the use of very large segments in the discretization of the state and therefore only one large segment is utilized when using this transcription.\n",
"The stronger optimality conditions come with the cost of additional iterations of the NLP solver but the resulting solutions typically have lower cost functions at the expense of additional compute time.\n",
"\n",
"## Satisfying Defects with a Nonlinear Solver\n",
"\n",
"Typically, collocation problems are solved by posing the defects as constraints to an optimizer.\n",
"In Dymos, another option exists.\n",
"One can use an embedded Newton-solver satisfy the defect and continuity constraints.\n",
"This mode, which we call `solve_segments`, gives the Newton-Solver control over all but the first or final state value in the phase.\n",
"The optimizer only controls the initial or final value, and the solver is responsible for converging the trajectory time history.\n",
"This results in a shooting method, but one that is mathematically consistent with the collocation methods.\n",
"This `solve_segments` capability is useful if a user simply wants to propagate a dynamic system and not optimize it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Tags",
"jupytext": {
"cell_metadata_filter": "-all",
"notebook_metadata_filter": "-all",
"text_representation": {
"extension": ".md",
"format_name": "markdown"
}
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}