Brachistochrone Problem#
Mathematical Formulation#
Problem Statement#
Find the optimal control angle
Subject to the dynamic constraints:
Boundary Conditions#
Initial conditions:
, ,Final conditions:
, , = freeControl bounds:
Physical Parameters#
Gravitational acceleration:
m/s²
State Variables#
: Horizontal position (m) : Vertical position (m) : Speed magnitude (m/s)
Control Variable#
: Path angle with respect to the vertical (rad)
Running This Example#
cd examples/brachistochrone
python brachistochrone.py
Code Implementation#
examples/brachistochrone/brachistochrone.py#
1import casadi as ca
2import numpy as np
3
4import maptor as mtor
5
6
7# Problem setup
8problem = mtor.Problem("Brachistochrone Problem")
9phase = problem.set_phase(1)
10
11# Variables
12t = phase.time(initial=0.0)
13x = phase.state("x", initial=0.0, final=2.0)
14y = phase.state("y", initial=0.0, final=2.0)
15v = phase.state("v", initial=0.0)
16theta = phase.control("u", boundary=(0.0, np.pi / 2))
17
18# Dynamics
19g = 9.81
20phase.dynamics({x: v * ca.sin(theta), y: v * ca.cos(theta), v: g * ca.cos(theta)})
21
22# Objective
23problem.minimize(t.final)
24
25# Mesh and guess
26phase.mesh([6], [-1.0, 1.0])
27
28states_guess = [
29 # Interval 1: 7 state points
30 [
31 [0.0, 1.0, 2.0, 3.0, 4.0, 4.5, 5.0], # x
32 [10.0, 9.5, 9.0, 8.5, 8.0, 7.5, 7.0], # y
33 [0.0, 1.0, 2.0, 2.5, 3.0, 3.5, 4.0], # v
34 ]
35]
36
37controls_guess = (
38 [
39 # Interval 1: 6 control points
40 [0.8, 0.7, 0.6, 0.5, 0.4, 0.3]
41 ],
42)
43
44
45phase.guess(
46 states=states_guess,
47 controls=controls_guess,
48 terminal_time=1.0,
49)
50# Solve with adaptive mesh
51solution = mtor.solve_adaptive(
52 problem,
53 error_tolerance=1e-6,
54 max_iterations=30,
55 min_polynomial_degree=3,
56 max_polynomial_degree=12,
57 nlp_options={"ipopt.print_level": 0, "ipopt.max_iter": 500},
58)
59
60# Results
61if solution.status["success"]:
62 print(f"Adaptive objective: {solution.status['objective']:.9f}")
63 solution.plot()
64
65 # Compare with fixed mesh
66 phase.mesh([6], [-1.0, 1.0])
67
68 states_guess = [
69 # Interval 1: 7 state points
70 [
71 [0.0, 1.0, 2.0, 3.0, 4.0, 4.5, 5.0], # x
72 [10.0, 9.5, 9.0, 8.5, 8.0, 7.5, 7.0], # y
73 [0.0, 1.0, 2.0, 2.5, 3.0, 3.5, 4.0], # v
74 ]
75 ]
76
77 controls_guess = (
78 [
79 # Interval 1: 6 control points
80 [0.8, 0.7, 0.6, 0.5, 0.4, 0.3]
81 ],
82 )
83
84 phase.guess(
85 states=states_guess,
86 controls=controls_guess,
87 terminal_time=1.0,
88 )
89
90 fixed_solution = mtor.solve_fixed_mesh(
91 problem, nlp_options={"ipopt.print_level": 0, "ipopt.max_iter": 500}
92 )
93
94 if fixed_solution.status["success"]:
95 print(f"Fixed mesh objective: {fixed_solution.status['objective']:.9f}")
96 print(
97 f"Difference: {abs(solution.status['objective'] - fixed_solution.status['objective']):.2e}"
98 )
99 fixed_solution.plot()
100 else:
101 print(f"Fixed mesh failed: {fixed_solution.status['message']}")
102
103else:
104 print(f"Failed: {solution.status['message']}")