Cart-Pole Optimal Control - Dymos
Cart-Pole Optimal Control - Dymos
html
Contents
• Trajectory Optimization Problem
• Implementing the ODE
• Building and running the problem
• References
This example is authored by Shugo Kaneko and Bernardo Pacini of the MDO Lab. The
cart-pole problem is an instructional case described in An introduction to trajectory
optimization: How to do your own direct collocation [Kel17], and is adapted to work
within Dymos. We consider a pole that can rotate freely attached to a cart, on which
we can exert an external force (control input) in the x-direction.
Our goal is to bring the cart-pole system from an initial state to a terminal state with
minimum control efforts. The initial state is the stable stationary point (the cart at a
stop with the pole vertically down), and the terminal state is the unstable stationary
state (the cart at a stop but with the pole vertically up). Friction force is ignored to
simplify the problem.
tf
J=∫ F (t) 2 dt → min (86)
t0
where F (t) is the external force, t 0 is the initial time, and t f is the final time.
Dynamics
The equations of motion of the cart-pole system are given by
ẍ −1 −g sin θ
cos θ ℓ
[ ]=[ ] [ ] (87)
θ¨ m1 + m2 m 2 ℓ cos θ F + m 2 ℓθ˙2 sin θ
where x is the cart location, θ is the pole angle, m 1 is the cart mass, m 2 is the pole
mass, and ℓ is the pole length.
Now, we need to convert the equations of motion, which are a second-order ODE, to
a first-order ODE. To do so, we define our state vector to be X = [x, ẋ, θ, θ]
˙ T . We
also add an “energy” state e and set ė = F 2 to keep track of the accumulated control
input. By setting setting e 0 = 0, the objective function is equal to the final value of the
state e:
tf
J=∫ ė dt = e f (88)
t0
⎡ ẋ ⎤
⎡ẋ⎤ ⎛⎡x⎤⎞ θ˙
θ˙ θ
−m 2 g sin θ cos θ−(F +m 2 ℓθ˙2 sin θ)
ẍ = f ẋ = m 2 cos 2 θ−(m 1 +m 2 ) (89)
¨ ˙
θ (m 1 +m ˙2
2 )g sin θ+cos θ(F +m 1 ℓθ sin θ)
θ
⎝⎣ e ⎦⎠ m 2 ℓ cos 2 θ−(m 1 +m 2 )ℓ
⎣ ė ⎦
⎣ F2 ⎦
xf =d
ẋ f =0
θf =π (90)
θ˙f =0
Parameters
The fixed parameters are summarized as follows.
tf 2 s Final time
import openmdao.api as om
om.display_source("dymos.examples.cart_pole.cartpole_dynamics")
"""
Cart-pole dynamics (ODE)
"""
import numpy as np
import openmdao.api as om
class CartPoleDynamics(om.ExplicitComponent):
"""
Computes the time derivatives of states given state variables and
control inputs.
Parameters
----------
m_cart : float
Mass of cart.
m_pole : float
Mass of pole.
l_pole : float
Length of pole.
theta : 1d array
Angle of pole, 0 for vertical downward, positive counter
clockwise.
theta_dot : 1d array
Angluar velocity of pole.
f : 1d array
x-wise force applied to the cart.
Returns
-------
x_dotdot : 1d array
Acceleration of cart in x direction.
theta_dotdot : 1d array
Angular acceleration of pole.
e_dot : 1d array
Rate of "energy" state.
"""
def initialize(self):
self.options.declare(
"num_nodes", default=1, desc="number of nodes to be evaluated
(i.e., length of vectors x, theta, etc)"
)
self.options.declare("g", default=9.81, desc="gravity constant")
def setup(self):
nn = self.options["num_nodes"]
sint = np.sin(theta)
cost = np.cos(theta)
det = mp * lpole * cost**2 - lpole * (mc + mp)
outputs["x_dotdot"] = (-mp * lpole * g * sint * cost - lpole * (f
+ mp * lpole * omega**2 * sint)) / det
outputs["theta_dotdot"] = ((mc + mp) * g * sint + cost * (f + mp *
lpole * omega**2 * sint)) / det
outputs["e_dot"] = f**2
"""
Cart-pole optimizatio runscript
"""
import numpy as np
import openmdao.api as om
import dymos as dm
from dymos.examples.plotting import plot_results
from dymos.examples.cart_pole.cartpole_dynamics import CartPoleDynamics
p = om.Problem()
<dymos.phase.phase.Phase at 0x7f216f3e1b40>
We set the terminal conditions as boundary constraints and declare the optimization
objective.
Next, we configure the optimizer and declare the total Jacobian coloring to accelerate
the derivative computations. We then call the setup method to setup the
OpenMDAO problem.
p.setup(check=False)
<openmdao.core.problem.Problem at 0x7f21d031e2f0>
Now we are ready to run optimization. But before that, set the initial optimization
variables using set_val methods to help convergence.
Full total jacobian for problem 'problem' was computed 3 times, taking
0.6736056480000343 seconds.
Total jacobian shape: (206, 281)
/usr/share/miniconda/envs/test/lib/python3.10/site-packages/openmdao/core/
group.py:1098: DerivativesWarning:Constraints or objectives
[ode_eval.control_interp.control_rates:f_rate2] cannot be impacted by the
design variables of the problem because no partials were defined for them
in their parent component(s).
False
After running optimization and simulation, the results can be plotted using the
plot_results function of Dymos.
References
[Kel17] Matthew Kelly. An introduction to trajectory optimization: How to do your
own direct collocation. SIAM Review, 59(4):849–904, 2017. doi:
10.1137/16M1062569.