@@ -293,3 +293,68 @@ savefig("plot4_LinMPC.svg"); nothing # hide
293293Note that measured disturbances are assumed constant in the future by default but custom
294294`` \mathbf{D̂} `` predictions are possible. The same applies for the setpoint predictions
295295`` \mathbf{R̂_y} `` .
296+
297+ ## Generating C code
298+
299+ The [ ` LinearMPC.jl ` ] (@extref LinearMPC) package extension provides code generation
300+ capabilities to export the controller as optimized C code. First, install the package with:
301+
302+ ``` test
303+ using Pkg; Pkg.add("LinearMPC")
304+ ```
305+
306+ The feedforward MPC controller can be converted to a [ ` LinearMPC.MPC ` ] ( @ref ) object using:
307+
308+ ``` @example 1
309+ import LinearMPC
310+ c_mpc_d = LinearMPC.MPC(mpc_d);
311+ ```
312+
313+ We test the converted controller in closed-loop to verify that it behaves identically to the
314+ original one:
315+
316+ ``` @example 1
317+ function test_c_mpc_d(c_mpc_d, model)
318+ N = 200
319+ ry, ul = [50, 30], 0
320+ dop = 20
321+ u = model.uop
322+ u_data, y_data, ry_data = zeros(model.nu, N), zeros(model.ny, N), zeros(model.ny, N)
323+ for i = 1:N
324+ i == 51 && (ry = [50, 35])
325+ i == 101 && (ry = [54, 30])
326+ i == 151 && (ul = -20)
327+ d = [ul .+ dop]
328+ y = model()
329+ x̂ = LinearMPC.correct_state!(c_mpc_d, y, d)
330+ u = LinearMPC.compute_control(c_mpc_d, x̂; r=ry, d=d, uprev=u)
331+ u_data[:,i], y_data[:,i], ry_data[:,i] = u, y, ry
332+ LinearMPC.predict_state!(c_mpc_d, u, d)
333+ updatestate!(model, u + [0; ul])
334+ end
335+ return u_data, y_data, ry_data
336+ end
337+ setstate!(model, zeros(model.nx))
338+ LinearMPC.set_state!(c_mpc_d, zeros(c_mpc_d.model.nx))
339+ u_data, y_data, ry_data = test_c_mpc_d(c_mpc_d, model)
340+ plot_data(t_data, u_data, y_data, ry_data)
341+ savefig("plot5_LinMPC.svg"); nothing # hide
342+ ```
343+
344+ ![ plot5_LinMPC] ( plot5_LinMPC.svg )
345+
346+ The closed-loop simulation matches the results of the previous section, as expected. We
347+ can now generate the C code using:
348+
349+ ``` julia
350+ LinearMPC. codegen (c_mpc_d; dir= " codegen" , fname= " mpc_funcs" )
351+ ```
352+
353+ The three C functions to call at each control periods are declared in the generated file
354+ ` codegen/mpc_funcs.h ` :
355+
356+ ``` C
357+ void mpc_correct_state (c_float* state, c_float* measurement, c_float* distrubance);
358+ int mpc_compute_control(c_float* control, c_float* state, c_float* reference, c_float* disturbance);
359+ void mpc_predict_state(c_float* state, c_float* control, c_float* disturbance);
360+ ```
0 commit comments