Container Crane Control#
Mathematical Formulation#
Problem Statement#
Find the optimal control inputs \(u_1(t)\) and \(u_2(t)\) that minimize the performance index:
Subject to the crane dynamic constraints:
Boundary Conditions#
Initial conditions: \(x_1(0) = 0\), \(x_2(0) = 22\), \(x_3(0) = 0\), \(x_4(0) = 0\), \(x_5(0) = -1\), \(x_6(0) = 0\)
Final conditions: \(x_1(t_f) = 10\), \(x_2(t_f) = 14\), \(x_3(t_f) = 0\), \(x_4(t_f) = 2.5\), \(x_5(t_f) = 0\), \(x_6(t_f) = 0\)
Control bounds: \(-c_1 \leq u_1 \leq c_1\), \(c_2 \leq u_2 \leq c_3\)
State bounds: \(-2.5 \leq x_4 \leq 2.5\), \(-1 \leq x_5 \leq 1\)
Physical Parameters#
Final time: \(t_f = 9.0\) s
Control penalty: \(\rho = 0.01\)
System constants: \(c_1 = 2.83374\), \(c_2 = -0.80865\), \(c_3 = 0.71265\), \(c_4 = 17.2656\), \(c_5 = 27.0756\)
State Variables#
\(x_1(t)\)
\(x_2(t)\)
\(x_3(t)\)
\(x_4(t)\)
\(x_5(t)\)
\(x_6(t)\)
Control Variables#
\(u_1(t)\)
\(u_2(t)\)
Notes#
This problem involves controlling a container crane to transport a load while minimizing swing oscillations and control effort.
Running This Example#
cd examples/container_crane
python container_crane.py
Code Implementation#
1import numpy as np
2
3import maptor as mtor
4
5
6# Constants
7p_rho = 0.01
8c1 = 2.83374
9c2 = -0.80865
10c3 = 0.71265
11c4 = 17.2656
12c5 = 27.0756
13t_final = 9.0
14
15# Problem setup
16problem = mtor.Problem("Container Crane")
17phase = problem.set_phase(1)
18
19# Variables
20t = phase.time(initial=0.0, final=t_final)
21x1 = phase.state("x1", initial=0.0, final=10.0)
22x2 = phase.state("x2", initial=22.0, final=14.0)
23x3 = phase.state("x3", initial=0.0, final=0.0)
24x4 = phase.state("x4", initial=0, final=2.5, boundary=(-2.5, 2.5))
25x5 = phase.state("x5", initial=-1, final=0.0, boundary=(-1.0, 1.0))
26x6 = phase.state("x6", initial=0.0, final=0.0)
27u1 = phase.control("u1", boundary=(-c1, c1))
28u2 = phase.control("u2", boundary=(c2, c3))
29
30# Dynamics
31phase.dynamics(
32 {
33 x1: x4,
34 x2: x5,
35 x3: x6,
36 x4: u1 + c4 * x3,
37 x5: u2,
38 x6: -(u1 + c5 * x3 + 2.0 * x5 * x6) / x2,
39 }
40)
41
42# Objective
43integrand = 0.5 * (x3**2 + x6**2 + p_rho * (u1**2 + u2**2))
44integral_var = phase.add_integral(integrand)
45problem.minimize(integral_var)
46
47# Mesh and guess
48phase.mesh([6, 6, 6], [-1.0, -1 / 3, 1 / 3, 1.0])
49
50states_guess = []
51controls_guess = []
52for N in [6, 6, 6]:
53 tau = np.linspace(-1, 1, N + 1)
54 t_norm = (tau + 1) / 2
55 x1_vals = 0.0 + (10.0 - 0.0) * t_norm
56 x2_vals = 22.0 + (14.0 - 22.0) * t_norm
57 x3_vals = 0.0 + (0.0 - 0.0) * t_norm
58 x4_vals = 0.0 + (2.5 - 0.0) * t_norm
59 x5_vals = -1.0 + (0.0 - (-1.0)) * t_norm
60 x6_vals = 0.0 + (0.0 - 0.0) * t_norm
61 states_guess.append(np.vstack([x1_vals, x2_vals, x3_vals, x4_vals, x5_vals, x6_vals]))
62
63 u1_mid = (-c1 + c1) / 2.0
64 u2_mid = (c2 + c3) / 2.0
65 controls_guess.append(np.vstack([np.full(N, u1_mid), np.full(N, u2_mid)]))
66
67phase.guess(states=states_guess, controls=controls_guess, integrals=0.1)
68
69# Solve
70solution = mtor.solve_adaptive(
71 problem,
72 error_tolerance=5e-7,
73 ode_method="Radau",
74 ode_solver_tolerance=1e-9,
75 nlp_options={"ipopt.print_level": 0, "ipopt.max_iter": 2000, "ipopt.tol": 1e-7},
76)
77
78# Results
79if solution.status["success"]:
80 print(f"Objective: {solution.status['objective']:.8f}")
81 print(
82 f"Reference: 0.0375195 (Error: {abs(solution.status['objective'] - 0.0375195) / 0.0375195 * 100:.2f}%)"
83 )
84 solution.plot()
85else:
86 print(f"Failed: {solution.status['message']}")