Skip to content

Commit 66b854f

Browse files
committed
init
1 parent 33bfbf6 commit 66b854f

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
using Test #src
2+
# # Example: Single Pendulum solved by [Uniform grid abstraction](https://github.com/dionysos-dev/Dionysos.jl/blob/master/docs/src/manual/manual.md#solvers).
3+
#
4+
# A simple pendulum is a typical example of a nonlinear dynamical system.
5+
# The pendulum's state is represented by its angular position ($x_1$ in radians) and angular velocity ($x_2$ in radians per second), and it is influenced by
6+
# gravitational forces ($g$ in meter per squared second), the length of the pendulum ($l$ in meter) and an external control input ($u$) that is a torque/force applied to modulate its behavior.
7+
# The objective is to drive the pendulum from a specified initial state (near the stable downward position)
8+
# to a target state (near the upright position), respecting constraints on both the state variables and the control input.
9+
#
10+
# The dynamics of the pendulum are given by:
11+
# ```math
12+
# dot(x_1) = x_2
13+
# dot(x_2) = -g/l \sin(x_1) + u
14+
# ```
15+
#
16+
# Considering this as a reachability problem, we will use it to showcase the capabilities of the Uniform grid abstraction solving typical problem in Dionysos.
17+
# The initial and target sets are defined as intervals in the state space.
18+
# x1_initial = [5.0 * pi / 180.0, -5.0 * pi / 180.0]
19+
# x2_initial = [0.5, -0.5]
20+
# x1_target = [pi + 5.0 * pi / 180.0, pi - 5.0 * pi / 180.0]
21+
# x2_target = [1.0, -1.0]
22+
23+
# First, let us import [StaticArrays](https://github.com/JuliaArrays/StaticArrays.jl) and [Plots](https://github.com/JuliaPlots/Plots.jl).
24+
using StaticArrays, Plots
25+
26+
# At this point, we import Dionysos and JuMP.
27+
using Dionysos, JuMP
28+
29+
# Define the problem using JuMP
30+
# We first create a JuMP model:
31+
model = Model(Dionysos.Optimizer)
32+
33+
# Define the discretization step
34+
hx = 0.05
35+
l = 1.0
36+
g = 9.81
37+
38+
# Define the state variables: x1(t), x2(t)
39+
x_low, x_upp = [-π, -10.0], [π + pi, 10.0]
40+
@variable(model, x_low[i] <= x[i = 1:2] <= x_upp[i])
41+
42+
# Define the control variables: u1(t), u2(t)
43+
@variable(model, -3.0 <= u <= 3.0)
44+
45+
# Define the dynamics
46+
@constraint(model, (x[1]) == x[2])
47+
@constraint(model, (x[2]) == -(g / l) * sin(x[1]) + u)
48+
49+
# Define the initial and target sets
50+
x1_initial, x2_initial = (5.0 * pi / 180.0) .* [-1, 1], 0.5 .* [-1, 1]
51+
x1_target, x2_target = pi .+ (5.0 * pi / 180.0) .* [-1, 1], 1.0 .* [-1, 1]
52+
53+
@constraint(model, start(x[1]) in MOI.Interval(x1_initial...))
54+
@constraint(model, start(x[2]) in MOI.Interval(x2_initial...))
55+
56+
@constraint(model, final(x[1]) in MOI.Interval(x1_target...))
57+
@constraint(model, final(x[2]) in MOI.Interval(x2_target...))
58+
59+
# ### Definition of the abstraction
60+
61+
# Definition of the grid of the state-space on which the abstraction is based (origin `x0` and state-space discretization `h`):
62+
63+
# We define the growth bound function of $f$:
64+
function jacobian_bound(u)
65+
return SMatrix{2, 2}(0.0, 1.0, (g / l), 0)
66+
end
67+
set_attribute(model, "jacobian_bound", jacobian_bound)
68+
69+
set_attribute(model, "time_step", 0.1)
70+
71+
x0 = SVector(0.0, 0.0);
72+
h = SVector(hx, hx);
73+
set_attribute(model, "state_grid", Dionysos.Domain.GridFree(x0, h))
74+
75+
# Definition of the grid of the input-space on which the abstraction is based (origin `u0` and input-space discretization `h`):
76+
u0 = SVector(0.0);
77+
h = SVector(0.3);
78+
set_attribute(model, "input_grid", Dionysos.Domain.GridFree(u0, h))
79+
80+
# Solving the problem
81+
optimize!(model)
82+
83+
# Get the results
84+
abstract_system = get_attribute(model, "abstract_system");
85+
abstract_problem = get_attribute(model, "abstract_problem");
86+
abstract_controller = get_attribute(model, "abstract_controller");
87+
concrete_controller = get_attribute(model, "concrete_controller")
88+
concrete_problem = get_attribute(model, "concrete_problem");
89+
concrete_system = concrete_problem.system
90+
91+
# ### Trajectory display
92+
nstep = 100
93+
function reached(x)
94+
if x concrete_problem.target_set
95+
return true
96+
else
97+
return false
98+
end
99+
end
100+
x0 = SVector(Dionysos.Utils.sample(concrete_problem.initial_set)...)
101+
control_trajectory = Dionysos.System.get_closed_loop_trajectory(
102+
get_attribute(model, "discretized_system"),
103+
concrete_controller,
104+
x0,
105+
nstep;
106+
stopping = reached,
107+
)
108+
109+
using Plots
110+
111+
# Here we display the coordinate projection on the two first components of the state space along the trajectory.
112+
fig = plot(; aspect_ratio = :equal);
113+
114+
# We display the concrete domain
115+
plot!(concrete_system.X);
116+
117+
# We display the abstract domain
118+
plot!(
119+
Dionysos.Symbolic.get_domain_from_symbols(
120+
abstract_system,
121+
abstract_problem.initial_set,
122+
);
123+
color = :green,
124+
opacity = 1.0,
125+
);
126+
plot!(
127+
Dionysos.Symbolic.get_domain_from_symbols(abstract_system, abstract_problem.target_set);
128+
color = :red,
129+
opacity = 1.0,
130+
);
131+
plot!(control_trajectory; markersize = 1, arrows = false)
132+
display(fig)

0 commit comments

Comments
 (0)