From b57339d4645fbb4819fe517a9ca0d35f05fac646 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson Date: Thu, 5 Sep 2024 05:45:17 +0200 Subject: [PATCH] add sliding mode control example --- docs/make.jl | 1 + docs/src/examples/sliding_mode_control.md | 93 +++++++++++++++++++++++ src/discrete_blocks.jl | 2 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 docs/src/examples/sliding_mode_control.md diff --git a/docs/make.jl b/docs/make.jl index 14ec4d3..ebb063f 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -33,6 +33,7 @@ makedocs(; "Examples" => [ "Controlled DC motor" => "examples/dc_motor_pi.md", "On-off controller" => "examples/onoffcontroller.md", + "Sliding-mode control" => "examples/sliding_mode_control.md", ], "Library API" => "blocks.md", ], diff --git a/docs/src/examples/sliding_mode_control.md b/docs/src/examples/sliding_mode_control.md new file mode 100644 index 0000000..57cfb12 --- /dev/null +++ b/docs/src/examples/sliding_mode_control.md @@ -0,0 +1,93 @@ +# Sliding-mode control +This example demonstrates how to model a system with a discrete-time sliding-mode controller using ModelingToolkit. The system consists of a second-order plant with a disturbance and a super-twisting sliding-mode controller. The controller is implemented as a discrete-time system, and the plant is modeled as a continuous-time system. + +When designing an SMC controller, we must choose a _switching function_ ``σ`` that produces the sliding variable ``s = σ(x, p, t)``. The sliding surface ``s=0`` must be chosen such that the sliding variable ``s`` exhibits desireable properties, i.e., converges to the desired state with stable dynamics. The control law is chosen to drive the system from any state ``x : s ≠ 0`` to the sliding surface ``s=0``. The sliding surface is commonly chosen as an asymptotically stable system with order equal to the ``n_x-n_u``, where ``n_x`` is the dimension of the state in the system to be controlled, and ``n_u`` is the number of inputs. + +Since the dynamics in this example is of relative degree ``r=2``, we will choose a switching surface corresponding to a stable first-order system (``r-1=1``). We will choose the system +```math +ė = -e +``` +which yields the switching variable ``s = ė + e``, encoded in the function ``s = σ(x, t)`` + +```@example ONOFF +using ModelingToolkit, ModelingToolkitSampledData, OrdinaryDiffEq, Plots +using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitStandardLibrary.Blocks +using JuliaSimCompiler +dt = 0.01 +clock = Clock(dt) +z = ShiftIndex(clock) + +qr(t) = 1sin(2t) # reference position +qdr(t) = 2cos(2t) # reference velocity + +function σ(x, t) + q, qd = x + e = q - qr(t) + ė = qd - qdr(t) + ė + e +end + +@register_symbolic σ(x, t::Real) + +@mtkmodel SuperTwistingSMC begin + @structural_parameters begin + z = ShiftIndex() + Ts = SampleTime() + nin + end + @components begin + input = RealInput(; nin) + output = RealOutput() + end + @parameters begin + k = 1, [description = "Control gain"] + k2 = 1.1, [description = "Tuning parameter, often set to 1.1"] + end + @variables begin + s(t) = 0.0, [description = "Sliding surface"] + p(t) = 0.0 + y(t) = 0.0, [description = "Control signal output"] + x(t) = 0.0 + xd(t) = 0.0 + end + @equations begin + s(z) ~ σ(input.u, t) + p ~ -√(k*abs(s))*sign(s) + xd ~ -k2*k*sign(s) + x(z) ~ x(z-1) + Ts*xd # Fwd Euler integration + y ~ p + x + output.u ~ y + end +end + + +@mtkmodel ClosedLoopModel begin + @components begin + plant = SecondOrder(;) + zoh = ZeroOrderHold() + controller = SuperTwistingSMC(nin = 2, k=50) + end + @variables begin + disturbance(t) = 0.0 + end + @equations begin + controller.input.u ~ [Sample(dt)(plant.x), Sample(dt)(plant.xd)] + disturbance ~ 2 + 2sin(3t) + sin(5t) + connect(controller.output, zoh.input) + zoh.output.u + disturbance ~ plant.input.u + end +end +@named m = ClosedLoopModel() +m = complete(m) +ssys = structural_simplify(IRSystem(m)) +prob = ODEProblem(ssys, [m.plant.x => -1, m.plant.xd => 0, m.controller.x(z-1) => 0], (0.0, 2π)) +sol = solve(prob, Tsit5(), dtmax=0.01) +figy = plot(sol, idxs=[m.plant.x]) +plot!(sol.t, qr.(sol.t), label="Reference") +figu = plot(sol, idxs=[m.zoh.y, m.disturbance], label=["Control signal" "Disturbance"]) +plot(figy, figu, layout=(2,1)) +``` + +The simulation indicates that the controller is able to track the reference signal despite the presence of the disturbance. The control signal exhibits a small degree of high-frequency chattering, a common characteristic of sliding-mode controllers. + diff --git a/src/discrete_blocks.jl b/src/discrete_blocks.jl index 197bba7..25b4417 100644 --- a/src/discrete_blocks.jl +++ b/src/discrete_blocks.jl @@ -987,7 +987,7 @@ Discrete-time On-Off controller with hysteresis. The controller switches between # Parameters: - `b`: Bandwidth around reference signal within which the controller does not react - `bool`: (structural) If true (default), the controller switches between 0 and 1. If false, the controller switches between -1 and 1. -- `k`: Controller gain. The output of the contorller is scaled by this gain, i.e., `k = 2, bool = false` will result in an output of -2 or 2. +- `k`: Controller gain. The output of the controller is scaled by this gain, i.e., `k = 2, bool = false` will result in an output of -2 or 2. """ @mtkmodel DiscreteOnOffController begin @extend u, y = siso = SISO()