# Deploying a Double Pendulum Model with Output Transform

This tutorial will demonstrate how to deploy a double pendulum model with a transformation of the outputs. The system evolves with states as polar coordinates of the position, but we will add a transformation such that the FMU outputs are Cartesian coordinates.

We start with importing `FMUGeneration`

and `OrdinaryDiffEq`

into our environment.

```
using FMUGeneration
using OrdinaryDiffEq
```

Let us clear our deployment workspace before we begin with the tutorial.

`clear_deployment_workspace()`

`[ Info: Cleared Deployment Workspace!`

We first define the system and the transforming function using `@define`

. The function `double_pendulum`

is our system. The function `polar2cart`

is the transforming function that converts the polar coordinates into cartesian. This example is taken from the `DifferentialEquations.jl docs`

```
@define begin
function double_pendulum(u, x, p, t)
m₁, m₂, L₁, L₂, g = p
du1 = u[2]
du2 = -((g * (2 * m₁ + m₂) * sin(u[1]) +
m₂ * (g * sin(u[1] - 2 * u[3]) +
2 * (L₂ * u[4]^2 + L₁ * u[2]^2 * cos(u[1] - u[3])) * sin(u[1] - u[3]))) /
(2 * L₁ * (m₁ + m₂ - m₂ * cos(u[1] - u[3])^2)))
du3 = u[4]
du4 = (((m₁ + m₂) * (L₁ * u[2]^2 + g * cos(u[1])) +
L₂ * m₂ * u[4]^2 * cos(u[1] - u[3])) * sin(u[1] - u[3])) /
(L₂ * (m₁ + m₂ - m₂ * cos(u[1] - u[3])^2))
[du1, du2, du3, du4]
end
function polar2cart(u, x, p, t)
l1 = p[3]
l2 = p[4]
vars = (2, 4)
p1 = l1 * u[vars[1]]
p2 = l2 * u[vars[2]]
x1 = l1 * sin(p1)
y1 = l1 * -cos(p1)
[x1 + l2 * sin.(p2), y1 - l2 * cos.(p2)]
end
end
```

Now that we have defined our system and transformation into the FMU Package, let us define the initial states, default parameters, and timespan for the system.

```
initial_states = [0, π / 3, 0, 3pi / 5]
m₁, m₂, L₁, L₂, g = 1, 2, 1, 2, 9.8
default_parameters = [m₁, m₂, L₁, L₂, g]
tspan = (0.0, 50.0)
tend = tspan[end]
param_names = ["m1", "m2", "L1", "L2", "g"]
state_names = ["alpha", "Lalpha", "beta", "Lbeta"]
output_names = ["x", "y"]
```

```
2-element Vector{String}:
"x"
"y"
```

We call `set_default`

and pass the keyword arguments necessary.

`set_default(; initial_states = initial_states, default_parameters = default_parameters, tspan = tspan)`

Now we define our `continuous model`

, in this case, it is the `double_pendulum`

function we have defined before.

`@continuous_model double_pendulum(u, x, p, t)`

And then, we define the `output transform`

that would convert the polar coordinates to cartesian coordinates.

`@output_transform polar2cart(u, x, p, t)`

We will add `OrdinaryDiffEq`

package to the FMU package using `@add_packages`

`@add_packages(["OrdinaryDiffEq", "SciMLBase"])`

```
[ Info: Pkg is already available in the sysimage.
[ Info: Base64 is already available in the sysimage.
[ Info: Future is already available in the sysimage.
[ Info: Sockets is already available in the sysimage.
[ Info: Markdown is already available in the sysimage.
[ Info: Tar is already available in the sysimage.
[ Info: UUIDs is already available in the sysimage.
[ Info: SHA is already available in the sysimage.
[ Info: LazyArtifacts is already available in the sysimage.
[ Info: LinearAlgebra is already available in the sysimage.
[ Info: ArgTools is already available in the sysimage.
[ Info: LibGit2 is already available in the sysimage.
[ Info: Artifacts is already available in the sysimage.
[ Info: Dates is already available in the sysimage.
[ Info: NetworkOptions is already available in the sysimage.
[ Info: MKL_jll is not explicitly added to the environment.
[ Info: Printf is already available in the sysimage.
[ Info: nghttp2_jll is already available in the sysimage.
[ Info: Test is already available in the sysimage.
[ Info: Random is already available in the sysimage.
[ Info: Libdl is already available in the sysimage.
[ Info: Serialization is already available in the sysimage.
[ Info: REPL is already available in the sysimage.
[ Info: libblastrampoline_jll is already available in the sysimage.
[ Info: MozillaCACerts_jll is already available in the sysimage.
[ Info: Mmap is already available in the sysimage.
[ Info: LibCURL_jll is already available in the sysimage.
[ Info: Logging is already available in the sysimage.
[ Info: TOML is already available in the sysimage.
[ Info: Downloads is already available in the sysimage.
[ Info: OpenBLAS_jll is already available in the sysimage.
[ Info: Distributed is already available in the sysimage.
[ Info: FileWatching is already available in the sysimage.
[ Info: LibCURL is already available in the sysimage.
[ Info: SharedArrays is already available in the sysimage.
[ Info: SparseArrays is already available in the sysimage.
[ Info: Unicode is already available in the sysimage.
[ Info: InteractiveUtils is already available in the sysimage.
[ Info: p7zip_jll is already available in the sysimage.
```

We then generate the FMU Package code using `generate_fmu_code`

`generate_fmu_code()`

We will import the package and get the package name using `@import_fmu_pkg`

`pkg_name, FMI2Binary = @import_fmu_pkg FMUGeneration.lib_path`

Now lets define the XML metadeta for the FMU with `generateXML`

We donot have inputs for this system and hence we define an empty vector for inputs.

```
inputs = NamedTuple[]
params = [(name = "$(param_names[i])", description = "desc p$i", start = default_parameters[i]) for i in 1:length(default_parameters)]
conts = [(name = "$(state_names[i])", unit = "unit c$i", description = "desc c$i", start = initial_states[i])
for i in 1:length(initial_states)]
outputs = [(name = "$o", unit = "unit c$i", description = "desc c$i")
for (i, o) in enumerate(["x", "y"])]
generateXML(inputs, params, conts, outputs, tend; sysname = "double_pendulum")
```

Now that we have defined our model, generated the FMU package, and generated the metadata, we are ready to compile a FMU. We call `compile_fmu`

`fmu_dir_path, fmu_path, fmu_so_file_path = compile_fmu()`

```
Pkg.rm(String(pkg_name)) # hide
nothing # hide
```